By Ahsan Khowaja · Updated 27 October 2026
How to use the color contrast checker
- Enter the text colour as a hex code, for example
#333333. Three-digit shorthand such as#333works too, with or without the#. - Enter the background colour the text sits on, for example
#FFFFFF. - Read the contrast ratio and the five pass/fail lines underneath: AA and AAA for normal text, AA and AAA for large text, and the 3:1 rule for buttons, icons and form borders.
The order doesn't matter: swapping text and background gives the same ratio, because the formula always puts the lighter colour on top. If you only have RGB values, turn them into a code with the RGB to hex converter first, and if you need to read a colour out of a screenshot or logo, the color picker from image gives you the hex.
The WCAG contrast ratio formula
The ratio comes from the WCAG 2.1 definition of contrast ratio. It is calculated from the relative luminance of each colour, a number from 0 (black) to 1 (white) that models how bright the colour looks to the eye:
Contrast ratio = (L1 + 0.05) ÷ (L2 + 0.05)
where L1 is the relative luminance of the lighter colour and L2 that of the darker one. The 0.05 stands for the light a screen reflects even when it shows black, which is why no pair can beat 21:1 and why the ratio is written as "something to one".
To get the relative luminance of a hex colour:
- Split the code into red, green and blue (0 to 255) and divide each by 255.
- Linearise each channel, because sRGB values are gamma-encoded: if the value is 0.04045 or less, divide it by 12.92; otherwise compute ((value + 0.055) ÷ 1.055)^2.4.
- Weight the channels by how sensitive we are to them: L = 0.2126 × R + 0.7152 × G + 0.0722 × B.
Green carries most of the weight and blue very little, which is why white text on pure blue (#0000FF) scores a comfortable 8.59:1 while white on pure green (#00FF00) scores only 1.37:1.
Worked example: #777777 on white
77 in hex is 119. 119 ÷ 255 = 0.4667. That is above 0.04045, so ((0.4667 + 0.055) ÷ 1.055)^2.4 = 0.1845. All three channels are the same, so L = 0.1845. White has L = 1. The ratio is (1 + 0.05) ÷ (0.1845 + 0.05) = 4.48:1, which fails the 4.5:1 minimum for normal text by a hair. The slightly darker #767676 gives 4.54:1 and passes, which is why that odd grey turns up in so many design systems.
AA vs AAA contrast: what the WCAG levels mean
| Success criterion | Level | Normal text | Large text | Applies to |
|---|---|---|---|---|
| 1.4.3 Contrast (Minimum) | AA | 4.5:1 | 3:1 | Body copy, labels, links, placeholder text |
| 1.4.6 Contrast (Enhanced) | AAA | 7:1 | 4.5:1 | Sites aiming at the strictest level |
| 1.4.11 Non-text Contrast | AA | 3:1 against adjacent colours | Button and input borders, focus rings, icons, chart lines |
The full wording is in WCAG 2.1, Success Criterion 1.4.3. A 4.5:1 contrast ratio is the number most people need: it is the AA requirement for normal text, and AA is the level most accessibility laws, procurement rules and audits ask for. AAA (7:1) is stricter and is usually reserved for reading-heavy content or sites with an older audience; W3C itself says AAA cannot be met for all content, so treat it as a goal, not a gate.
Two kinds of content are exempt from 1.4.3: text that is purely decorative or part of an inactive control, and text inside a logo or brand name. Disabled buttons can therefore be low-contrast, but the text in a placeholder or a "hint" cannot.
Large text contrast: what counts as large
WCAG defines large text as at least 18 point, or 14 point bold. On the web a CSS point is 1⅓ pixels, so that is about 24px regular or 18.7px bold. Large text only needs 3:1 for AA and 4.5:1 for AAA, because bigger strokes are easier to read at lower contrast. This is why white on pure red (#FF0000, 4.00:1) is fine for a big hero heading but fails for a paragraph. Use the font size calculator to see which heading sizes in your type scale are over the 24px line, and the px to rem converter if your stylesheet uses rem.
Non-text contrast: buttons, icons and inputs
Since WCAG 2.1, the parts of a control you need to see in order to use it (a button's edge, an input's border, a checkbox, a focus ring) and any graphic needed to understand content (an icon without a label, a chart line) need 3:1 against the colours next to them. A button with a dark fill and white label passes if the label has 4.5:1 against the fill; the fill itself only needs 3:1 against the page if the edge is what tells you it is a button. Check both pairs: label against fill, and fill against the page background. Light-grey input borders such as #CCCCCC on white are the most common failure here at 1.6:1.
Common colour pairs and their ratios
| Text | Background | Ratio | AA normal | AAA normal |
|---|---|---|---|---|
| #000000 | #FFFFFF | 21.00:1 | Pass | Pass |
| #333333 | #FFFFFF | 12.63:1 | Pass | Pass |
| #595959 | #FFFFFF | 7.00:1 | Pass | Pass |
| #767676 | #FFFFFF | 4.54:1 | Pass | Fail |
| #777777 | #FFFFFF | 4.48:1 | Fail | Fail |
| #949494 | #FFFFFF | 3.03:1 | Fail (large text only) | Fail |
| #FFFFFF | #0000FF | 8.59:1 | Pass | Pass |
| #FFFFFF | #FF0000 | 4.00:1 | Fail (large text only) | Fail |
| #000000 | #FFFF00 | 19.56:1 | Pass | Pass |
| #FFFFFF | #00FF00 | 1.37:1 | Fail | Fail |
#595959 is the lightest grey that reaches 7:1 on white, and #949494 the lightest that reaches 3:1, so those two and #767676 are useful ceilings when you are picking greys for a light theme.
How to fix a failing pair
Contrast depends on luminance, not hue, so the fix is almost always to make the dark colour darker or the light colour lighter rather than to change the hue. Each step helps:
- Darken text by a few hex steps and re-check; moving from
#777777to#767676was enough to cross 4.5:1 above. - Avoid mid-tones for text. A saturated orange or light blue on white rarely clears 3:1, so use it for large headings or put it on a dark background instead.
- Check text over photos at the darkest and lightest points of the image, or add a solid or gradient overlay behind it.
- For dark mode, test the pair again: light text on
#121212behaves differently from dark text on white, and pure white on pure black (21:1) can look harsh, so many dark themes use#E0E0E0text instead, which still gives 14.19:1.
Limits of the WCAG 2.x ratio and APCA
The 2.x formula treats colours symmetrically and ignores font weight, so it sometimes passes thin light text on dark that is hard to read, and fails some dark-on-light pairs that look fine. The W3C's WCAG 3 working draft explores a new method, the Accessible Perceptual Contrast Algorithm (APCA), which scores pairs on a different scale and takes text size and weight into account. It is still a draft and not a requirement anywhere, so this checker reports the WCAG 2.1 ratio, which is what every current standard, audit tool and legal reference uses. Also remember that the ratio assumes opaque colours: if your text or background has transparency, flatten it against what is behind it first, and if you work in a wide-gamut colour space, read our guide to sRGB and Display P3 colour profiles, because the formula is defined for sRGB.
