Colour converter and contrast checker
Every format for one colour, and the WCAG contrast ratio against another. Hex, RGB, HSL and OKLCH, with the ratio checked against the three thresholds that matter — 4.5:1 for body text, 3:1 for large text and interface components, 7:1 for AAA.
The luminance is computed the way the specification defines it, from linearised channels. Skipping that step is the commonest bug in contrast checkers, and it moves mid-tones across the pass line.
Body text at the size most of a page is set in.
Large text, 24px
- ✓ Body text needs 4.5
- ✓ Large text and buttons needs 3
- ✓ Body text, enhanced needs 7
Large means 24px, or 19px bold. The 3:1 line also covers icons, form borders and anything else a person has to make out to use the page.
- Hex
#1f2933 - Hex with alpha
#1f2933 - RGB
rgb(31 41 51) - HSL
hsl(210 24.4% 16.1%) - OKLCH
oklch(27.6% 0.0233 248.7)
Nothing is uploaded. Converted in this tab, and no request is made while you use it.
The step contrast checkers skip
WCAG defines the contrast ratio precisely, and the definition has a step in the middle that is easy to leave out. Relative luminance is not a weighted average of the red, green and blue numbers in your hex code. Those numbers are gamma-encoded: the sRGB value 128 is not half the light of 255.
Each channel has to be converted back to linear light first, and only then weighted — 0.2126 red, 0.7152 green, 0.0722 blue, which is why green dominates and blue barely registers. Skip the linearisation and mid-tones come out far too bright.
| Colour on white | Raw sRGB weighted | Correct | Passes AA? |
|---|---|---|---|
#777777 | 2.03:1 | 4.48:1 | Just fails |
#767676 | 2.05:1 | 4.54:1 | Just passes |
#000000 | 21:1 | 21:1 | Yes |
The other half of the definition is the order. The ratio is
(lighter + 0.05) / (darker + 0.05), so it must not matter which colour you enter first — swap
them here and the number does not move. Implementations that divide foreground by background return the
reciprocal half the time, which produces ratios below 1 that no threshold was ever written for.
What the thresholds actually cover
| Ratio | Level | Applies to |
|---|---|---|
| 3:1 | AA | Text at 24px, or 19px bold. Icons, form borders, focus rings. |
| 4.5:1 | AA | Body text. The one most legislation points at. |
| 7:1 | AAA | Body text, enhanced. Rare outside text-heavy sites. |
The 3:1 row is the one that gets missed. WCAG 1.4.11 applies it to user interface components, so a text input whose border is a pale grey on white fails even if every word on the page passes. A disabled control is exempt; a control that merely looks disabled is not.
HSL, and why OKLCH replaced it
HSL was an improvement on hex because its numbers mean something: change the hue and you get a different colour at the same intensity. Except you do not, quite. HSL lightness is arithmetic, not perceptual.
hsl(60 100% 50%) and hsl(240 100% 50%) claim the same lightness. The first is
yellow, which is almost too bright to read against white; the second is a deep blue that white text sits on
comfortably. Their actual luminances differ by a factor of more than twenty. Any palette generated by holding
HSL lightness constant will have some steps that vanish and others that shout.
OKLCH fixes exactly that. It is built on the Oklab perceptual model, so equal lightness values look equally bright regardless of hue, and equal chroma steps look equally saturated. Every current browser supports it in CSS. For a hand-picked colour it changes nothing; for a generated scale it is the difference between a ramp that works and one that needs eyeballing at every step.
Reading the hex shorthand
#abc is not #0a0b0c. Each digit is doubled, so it means #aabbcc — which
is why the shorthand can only express 4,096 of the 16.7 million colours, and why the ones it can express are
the ones you see in old stylesheets.
The four and eight digit forms add alpha on the end: #ff000080 is red at 50%. All four lengths
are accepted here, with or without the hash, as are rgb() and hsl() in both the
legacy comma syntax and the modern space-separated one with a slash before the alpha.
Why the preview is there
A ratio is a number and numbers do not have a look. 4.4:1 and 4.6:1 are on opposite sides of a legal threshold and are visually indistinguishable, while 8:1 and 15:1 both simply read as "fine".
So the two colours are shown as text on a background at both sizes the specification distinguishes, above the verdict rather than beside it. The number tells you whether it complies. The preview tells you whether it is any good, which is a different question and the one your readers will answer.
Questions
How do I convert a hex colour to RGB?
Type or paste it into the text colour box — with or without the #, in three, four, six or eight digits — and every other format appears below, each with a copy button. It works the other way too: paste rgb(51 102 204) or hsl(220 60% 50%) and you get the hex.
What contrast ratio do I need?
4.5:1 for body text and 3:1 for large text, to meet WCAG AA — which is the level referenced by the UK Equality Act, the European Accessibility Act and Section 508. Large means 24px, or 19px bold. The 3:1 line also covers icons, form field borders and anything else someone has to make out to use the page. AAA asks for 7:1, which is a high bar for brand colours and is usually reserved for text-heavy pages.
Why does your contrast ratio differ from another checker?
Almost always because the other one skips linearisation. Relative luminance is computed from gamma-corrected channel values, not from the raw sRGB numbers, and skipping that step inflates mid-tones badly. A mid grey on white is 4.48:1 done properly and 2.03:1 if the raw sRGB values are weighted directly — the difference between passing AA and failing it, with nothing on screen to show which you got.
What is OKLCH and should I use it?
A perceptual colour space, supported in every current browser. Its lightness matches what the eye sees, so two colours with the same L look equally bright — which HSL does not manage: hsl(60 100% 50%) is yellow and hsl(240 100% 50%) is blue, both nominally 50% lightness, and one is blinding while the other is nearly black. That makes OKLCH far better for generating a palette or a set of tints programmatically.
Does contrast apply to icons and buttons?
Yes. WCAG 1.4.11 requires 3:1 for user interface components and meaningful graphics — the border of a text input, a toggle in its off state, the outline of an icon button. It is the most commonly missed criterion, because it is easy to check text and easy to forget that a form field nobody can see the edge of is also a failure.
Is a colour with transparency handled?
The alpha channel is parsed, shown and converted, but the contrast ratio uses the colour as given. WCAG contrast is defined for the colours that actually meet the eye, so a semi-transparent foreground has to be composited against its real background first. If the numbers matter, work out the flattened colour and check that.
What BriskFile will not do to you
-
Your files never leave your device
Every conversion runs in your browser. Open DevTools, watch the Network tab, and you will see no upload — because there is not one.
-
No account, no email, no watermark
Nothing to sign up for and nothing stamped on your images. There is no step between choosing a file and getting it back.
-
No limits at the download button
No daily cap, no file counter, no "upgrade to download". If the tool starts a job, it finishes it.
-
Checkable, not just claimed
Open the Network tab and convert something — nothing goes out. Or load the page, disconnect, and watch it keep working: the tool is already on your machine, and your file never leaves it.