Accessibility
A Practical Guide to WCAG Color Contrast
Contrast ratios are the single best leading indicator of whether your text will be readable to a wide audience. Learn the formula, the thresholds, and where the rules give designers more room than they expect.
Why contrast matters
Roughly one in twelve men and one in two hundred women experience some form of color vision deficiency. A larger group has reduced contrast sensitivity from age, glare, fatigue, low-quality screens, or harsh sunlight on a phone. Color contrast — the relative brightness of text against its background — is the single design decision that affects all of those readers at once.
The Web Content Accessibility Guidelines (WCAG 2.1 and onwards) define numeric thresholds so the call is not subjective. The home contrast checker implements those thresholds; this page explains what they mean and where they leave room for judgement.
The contrast ratio
Contrast ratio compares the relative luminance of two colors. The ratio runs from 1:1 (identical colors, invisible) to 21:1 (pure black on pure white). The formula:
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
Where L is the relative luminance of each color. Luminance itself is computed by gamma-correcting each RGB channel and then weighting them — green contributes most, then red, then blue:
L = 0.2126 × R + 0.7152 × G + 0.0722 × B
(Channels are first linearised by reversing the sRGB gamma curve.) The takeaway: blue contributes very little to luminance, which is why pure blue text on a black background tests as poor contrast even though it looks "different." It's the same lightness as the background, just a different hue.
The thresholds
| Level | Normal text | Large text | UI components |
|---|---|---|---|
| WCAG 2.1 AA | 4.5 : 1 | 3 : 1 | 3 : 1 |
| WCAG 2.1 AAA | 7 : 1 | 4.5 : 1 | — |
"Normal text" is anything below 18pt regular or 14pt bold. "Large text" is at or above those thresholds. "UI components" covers actionable graphical elements — focus rings, icons that carry meaning, the visual edges of inputs. Decorative imagery, logotypes, and inactive UI are exempt.
Which level to target
- AA is the legal floor in many jurisdictions and the realistic target for most consumer products. Hitting AA is a strong baseline.
- AAA is the gold standard, but enforcing 7:1 across an entire color system can flatten brand expression. AAA is most worthwhile on dense reading surfaces — long-form articles, documentation, dashboards with small numeric labels.
- Below AA is appropriate only for incidental or disabled elements (placeholder text becomes readable on focus, ghost buttons are contextual, etc.) — and even then, treat it as a deliberate exception.
A worked example
Take a button: white text on a brand purple. The brand color is #6C5CE7, which has a relative luminance of about 0.149. White is 1.0. Plug into the formula:
(1.0 + 0.05) / (0.149 + 0.05) = 5.27 : 1
5.27 passes AA for normal text (≥ 4.5) but fails AAA for normal text (< 7). For a primary button label that's fine. For 12px helper text on the same background, the message is the same — 5.27 still passes AA — but legibility will start to suffer because contrast minimums alone don't account for tiny type.
If the same purple is used as text on a white background, the ratio is identical (the formula is symmetric). If the background changes to a near-white #F2F2F4, the ratio drops only slightly to about 4.84 — still passing AA. If the background changes to mid-gray #9999A0, the ratio drops to about 1.9, which fails everything.
Where the rules surprise people
1. Big numbers can hide small text
WCAG considers a button label "large text" only at 18pt regular or 14pt bold. A 14pt label at regular weight is still "normal text" and needs the full 4.5:1 ratio. Designers regularly design at the borderline weight and assume the looser threshold.
2. Disabled controls are exempt
WCAG explicitly excludes inactive UI components from the 3:1 requirement. That doesn't mean disabled buttons should be invisible — it means the contrast rule doesn't trip a violation. Practical advice: keep disabled affordances visible enough that users understand what's interactive when re-enabled.
3. Logos are exempt
Brand marks and "essential" decorative imagery don't have to meet a contrast ratio. A heritage wordmark on its native background is allowed even if it tests poorly. The exemption does not extend to logo-shaped buttons that carry interactive meaning.
4. Placeholder text is text
The default browser styling for ::placeholder often falls below 4.5:1. If the placeholder communicates anything other than "type here," treat it as normal text and check the contrast.
5. Transparency changes everything
The contrast checker assumes solid colors. The moment alpha is introduced — semi-transparent text or a translucent overlay — the visible color depends on what is behind it. Compute the ratio against the resolved color, not the unblended foreground. The RGBA & transparency guide covers the math.
Beyond the ratio
Hitting 4.5:1 is necessary but not sufficient. Several factors influence real-world readability that the formula doesn't capture:
- Font weight. Hairline weights (200, 300) read worse than the same color at regular weight. If the design uses a thin font, raise the contrast deliberately.
- Anti-aliasing. Sub-pixel rendering on light backgrounds is more forgiving than dark-on-dark, where common rendering settings can leave letterforms looking thin. Bumping body text from 4.5:1 to 7:1 on dark themes pays off.
- Color blindness. Two colors can pass the contrast threshold and still be confusable to a deuteranope (red-green deficiency). Don't rely on color alone to communicate state — pair color with shape, weight, or text labels.
- Ambient light. A dashboard tested at desk light may be unreadable in direct sunlight. Mobile-first products often need higher contrast than the minimum.
A workflow that catches problems early
- Define the palette in tokens, with each pair (text, background) annotated by its tested contrast ratio.
- Pick the smallest text size in the system and validate that the lightest text-on-background combination still passes AA.
- Verify focus indicators against both their default and active backgrounds — the 3:1 rule applies to the focus ring itself.
- Spot-check with the home contrast checker while designing; integrate an automated check (axe-core, Lighthouse) into CI for catching regressions.
- Test the result on a real device under bright light, with a color-blindness simulator, and at the smallest text size in the design.
Common mistakes
- Designing only on a calibrated monitor. Most users don't have one. Build for the worst common case, not the best.
- Using lightness as a proxy for contrast. Two HSL values with the same lightness can differ wildly in luminance. Always use the actual ratio.
- Letting brand color drive body text. Brand colors live in headlines, accents, and large UI. They almost never satisfy 4.5:1 against white, and forcing them to do so produces boring results. Use neutral text colors and let the brand color do the highlighting.
- Treating AAA as a checklist item. Hitting AAA for everything tends to flatten a design. Pick the surfaces that benefit (long-form text, dense data) and target AAA there.
Where to learn more
The official source is the WCAG 2.1 specification, particularly Success Criterion 1.4.3 (Contrast Minimum) and 1.4.6 (Contrast Enhanced). The W3C also publishes detailed Understanding documents that walk through the rationale and exceptions.
Quick reference
- AA: 4.5:1 for body, 3:1 for large text and UI.
- AAA: 7:1 for body, 4.5:1 for large text.
- Normal text = below 18pt regular / 14pt bold.
- Use the actual ratio, not lightness, to judge accessibility.
- Test transparent foregrounds against the resolved color.
- Pair color with another cue so users with color vision deficiency aren't excluded.