Good colour contrast is the single most impactful accessibility improvement most design teams can ship in an afternoon. This WCAG Contrast Checker applies the exact W3C formula — full sRGB linearization, no shortcuts — to give you a reliable contrast ratio, instant AA and AAA pass/fail results, a live text preview, and a one-click suggestion to fix failing combinations.
How the maths work
The WCAG contrast algorithm has three stages:
Stage 1 — sRGB linearization. Each 8-bit channel of your hex colour (0–255) is normalised to the [0, 1] range and then “linearized” to remove the display gamma applied by monitors. The piecewise function from IEC 61966-2-1 is used: values at or below 0.04045 are divided by 12.92; values above that are raised to the 2.4 power after a small offset: ((c + 0.055) / 1.055)^2.4. This step is what makes the formula physically correct rather than merely perceptual.
Stage 2 — Relative luminance. The three linearized channels are combined using ITU-R BT.709 coefficients — the same primaries used for sRGB displays — to produce a single luminance value L: L = 0.2126·R + 0.7152·G + 0.0722·B. Green carries the most weight (72%) because the human eye is most sensitive to green wavelengths.
Stage 3 — Contrast ratio. Given luminances L1 (lighter) and L2 (darker), the ratio is (L1 + 0.05) / (L2 + 0.05). The 0.05 offset prevents division by zero when comparing pure black against itself, and also reflects the small amount of light that any real display emits even in pure-black pixels.
WCAG thresholds at a glance
| Level | Text size | Minimum ratio |
|---|---|---|
| AA | Normal (below 18pt / 14pt bold) | 4.5:1 |
| AA | Large (18pt+ or 14pt+ bold) / UI components | 3.0:1 |
| AAA | Normal text — enhanced | 7.0:1 |
| AAA | Large text — enhanced | 4.5:1 |
Worked example
Foreground #1a1a2e on background #ffffff:
- Linearize
#1a1a2e→ R = 26, G = 26, B = 46. All three channel values (26/255 ≈ 0.102, 46/255 ≈ 0.180) exceed 0.04045, so the pow branch applies. Linear R = ((26/255 + 0.055) / 1.055)^2.4 ≈ 0.01033; same for G; Linear B ≈ 0.02732. - L(foreground) = 0.2126·0.01033 + 0.7152·0.01033 + 0.0722·0.02732 ≈ 0.01156.
- L(background white) = 1.0 (trivially, since all channels = 255).
- Ratio = (1.0 + 0.05) / (0.01156 + 0.05) = 1.05 / 0.06156 ≈ 17.06:1 — AAA for all text sizes.
Now try #5a5a5a (a dark grey) on white: L ≈ 0.1022, ratio ≈ (1.05) / (0.1522) ≈ 6.90:1 — that fails AAA for normal text (needs 7.0:1) but comfortably passes AA. For a pair that fails AA normal text entirely, try #9e9e9e on white: L ≈ 0.3419, ratio ≈ (1.05) / (0.3919) ≈ 2.68:1 — fails all text thresholds (below 3.0:1).
Fix suggestion algorithm
When a pair fails AA for normal text, the tool finds the nearest compliant foreground colour. It converts the foreground to HSL, preserves hue and saturation exactly, then steps lightness in increments of 0.001 toward both 0 (darkening) and 1 (lightening) until the 4.5:1 threshold is met. The direction with the smaller lightness delta is returned, ensuring the brand colour changes as little as possible.