WCAG Color Contrast Explained: How to Pass AA and AAA (With Real Examples)
"Make sure the contrast passes" is common design-review advice, but the ratio behind it is a specific, computable number — not a subjective call. Knowing what's actually being measured makes it much faster to spot a failure before it ships, instead of after an audit flags it.
The thresholds that matter
| Criterion | Text size | Minimum ratio |
|---|---|---|
| WCAG AA (1.4.3) | Normal text | 4.5:1 |
| WCAG AA (1.4.3) | Large text (≥24px, or ≥18.66px bold) | 3:1 |
| WCAG AAA (1.4.6) | Normal text | 7:1 |
| WCAG AAA (1.4.6) | Large text | 4.5:1 |
| Non-text contrast (1.4.11) | UI components, graphics, focus indicators | 3:1 |
"Large text" specifically means 18pt (24px) regular weight or 14pt (about 18.66px) bold — it's a size-and-weight threshold, not just "looks big."
Where the ratio actually comes from
Contrast ratio is computed from each color's relative luminance — a measure of how much light it reflects, on a 0 (black) to 1 (white) scale, gamma-corrected to match human perception rather than raw RGB values. For an sRGB color, each channel is first normalized to 0–1, then linearized:
c = channel / 255
c_lin = c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4
Relative luminance combines the three linearized channels with weights that reflect how sensitive human vision is to each — green contributes the most, blue the least:
L = 0.2126 * R_lin + 0.7152 * G_lin + 0.0722 * B_lin
The contrast ratio between two colors is then the lighter luminance plus a small offset, over the darker luminance plus the same offset:
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
The result ranges from 1:1 (identical colors, no contrast at all) to 21:1 (pure black on pure white).
A worked example
Take this site's own ink-on-background pairing: #201b39 text on a #f2f8f5 page
background. Running both through the formula above gives a relative luminance around 0.018 for the dark
ink and about 0.936 for the near-white background, which puts the ratio at roughly:
(0.936 + 0.05) / (0.018 + 0.05) ≈ 14.5:1
That comfortably clears even the strictest AAA-normal-text threshold of 7:1 — which is exactly the point of checking the number rather than eyeballing it: a color pair that "looks plenty dark" can still land anywhere from 3:1 to 15:1 depending on the exact values, and only the computed ratio tells you which.
Failures that look fine until you measure them
- Light gray body text on white — a popular "soft" aesthetic that frequently lands between 2.5:1 and 3.5:1, well under the 4.5:1 normal-text minimum.
- Placeholder text — often styled deliberately faint to look "inactive," which then fails contrast for anyone who actually needs to read it, including low-vision users with no visual impairment relevant to the placeholder's intended meaning.
- Brand color as body text — a saturated brand hue picked for buttons and accents often fails as small paragraph text, because saturation and lightness that read well in a 40px logo can be far too light at 16px on a white page.
- Disabled-looking but actually interactive elements — a low-contrast "disabled" style applied to something a user can still click confuses two different signals: contrast and interactivity.
- Text over a photo or gradient — a single fixed text color can pass in the darkest region of an image and fail in the lightest; the ratio has to be checked against the worst-case region the text overlaps, not an average.
Why the ratio includes a +0.05 offset
The 0.05 added to both luminance values in the ratio formula accounts for ambient light
scattering on a real screen — pure black never reflects literally zero light in practice, so the formula
avoids a division that would otherwise treat true black as infinitely dark relative to anything else. It's
a small constant, but it's why the maximum possible ratio (pure black on pure white) comes out to exactly
21:1 rather than an undefined or infinite value.
Non-text contrast: icons, borders, and focus indicators
WCAG's 1.4.11 criterion applies the same kind of ratio check to non-text UI — the visible outline of a form input, an icon that conveys meaning on its own, a focus indicator — with a 3:1 minimum against its immediate background. A checkbox rendered as a faint 1px gray line on a white background, or a focus ring that's only a couple of shades different from the element it surrounds, commonly fails this even when the surrounding text passes comfortably — it's a separate check, not automatically covered by a page's text contrast being fine.
A large-text example
Take a 32px bold heading in a medium gray, #6b7280, on a white background. Running the
luminance formula gives roughly 5.5:1 — which fails the stricter AAA-normal 7:1 threshold, but passes AA
comfortably for large text (3:1 minimum) since 32px bold clears the "large text" size-and-weight threshold.
The same exact gray used for a 14px regular-weight caption underneath that heading would need to clear
4.5:1 instead, and at 5.5:1 it would pass there too — but drop the caption to a slightly lighter gray and it
could fail the caption while the heading above it still passes, since they're checked against different
thresholds entirely.
Checking it in practice
Most browser devtools now surface a contrast ratio directly in the color picker when you inspect a text element, which is the fastest in-context check. For picking or auditing a pairing before it's in the DOM at all — during design review, or when proposing a new brand color — the WCAG contrast ratio checker gives the exact ratio and a pass/fail against AA and AAA for both normal and large text in one step.
Contrast is a legal requirement in more places than it used to be
Beyond WCAG as a voluntary standard, a growing number of jurisdictions reference it directly in digital accessibility law — the U.S. has seen a steady rise in ADA-related web accessibility litigation citing WCAG conformance, and the EU's accessibility directives point to the same criteria. Treating contrast (and accessibility generally) as a legal-risk question rather than purely a design-polish one is increasingly accurate for any site serving the public, not just a nice-to-have.
Frequently Asked Questions
Does passing contrast mean an interface is accessible?
No — contrast is one requirement among many. Keyboard operability, focus order, semantic markup, and not conveying meaning through color alone all matter independently of the contrast ratio.
Do contrast requirements apply to disabled form fields?
WCAG explicitly exempts inactive/disabled UI components from the contrast requirement, since they're not meant to be operated — but the moment an element is genuinely interactive, the requirement applies.
Does a contrast checker account for colorblindness?
Not directly — the ratio is computed from luminance, which is largely color-vision-independent, but distinguishing two similarly-lit, differently-hued colors from each other is a separate concern from text legibility and needs its own check (e.g., not relying on red vs. green alone to convey status).
What about large, bold headings — do they need less contrast?
Yes, by the WCAG large-text definition (≥24px regular or ≥18.66px bold) the AA minimum drops to 3:1 instead of 4.5:1, reflecting that bigger, heavier strokes stay legible at lower contrast.
Is a higher contrast ratio always better?
Not necessarily for comfort — pure black on pure white (21:1) can feel harsh for long-form reading, which is why many text-heavy sites intentionally use a slightly softened near-black on a near-white background, as long as the resulting ratio still comfortably clears 4.5:1 or 7:1.
Does contrast checking apply to dark mode too?
Yes, independently — a color pair verified in a light theme tells you nothing about the same brand color against a dark theme's background, so each theme's text/background pairs need their own check.