Guide
Color contrast for accessibility: WCAG 2.1, APCA, and what to actually ship
WCAG 4.5:1 is the legal floor. It's also a flawed formula. Here's the modern picture.
By Buğra SözeriPublished Updated
WCAG 2.1 requires 4.5:1 contrast ratio for regular body text and 3:1for large text (18pt+ regular or 14pt+ bold). The formula is the de-facto legal standard in the US (ADA-relevant), EU (EAA), and most of the world. It also has well-documented flaws that have spawned a replacement (APCA) which didn’t make WCAG 2.2. This guide explains the practical picture today.
The WCAG 2.x contrast formula
Defined in WCAG 2.0 (2008) and unchanged through 2.2:
contrast = (L_light + 0.05) / (L_dark + 0.05)
where L = relative luminance (0-1) of each colour, computed in linear-light sRGBResults range from 1:1 (identical colours) to 21:1 (pure white on pure black).
WCAG thresholds (for AA compliance, the standard target):
- 4.5:1 — body text, icons, form controls.
- 3:1 — large text (≥ 18pt or ≥ 14pt bold), UI components (button borders, focus indicators).
- AAA targets are stricter: 7:1 body, 4.5:1 large. Required only in some specific contexts (legal text, government).
Where the formula is wrong
Three documented problems:
- Mid-tone insensitivity. The formula gives equal contrast scores to mid-tone pairs (e.g., grey on grey) that look very different in actual perception. A 4.5:1 pair of mid-greys can be visually weaker than a 3:1 pair of black on light grey.
- Hue-blind.Equal-luminance hues (red and green at the same brightness) score 1:1 contrast, but dichromat users may discriminate them poorly anyway. The formula can’t detect colour-blindness issues.
- Font weight ignored.Thin fonts need more contrast than bold fonts at the same size; WCAG gives no credit for weight beyond the binary “large text” threshold.
APCA: the replacement that didn’t make WCAG 2.2
APCA (Accessible Perceptual Contrast Algorithm) is the proposed-and-rejected next-generation contrast metric. Developed by Andrew Somers for WCAG 3.0 working draft. It accounts for the issues above and is dramatically more accurate against actual user-study data.
APCA scores range −108 to +106. Positive means dark text on light background; negative means the reverse. Thresholds:
- Lc 75 — body text (replaces WCAG’s 4.5:1).
- Lc 60 — large text or headlines (replaces 3:1).
- Lc 45 — non-content text (decorative, copyright lines).
APCA gives different thresholds per direction (light-on-dark vs dark-on-light) because human eyes process the two cases differently. WCAG’s symmetric formula misses this.
What to use in 2026
Two-track approach:
- Pass WCAG 2.1 AA at minimum.It’s the legal standard. Use the standard ratio formula, target 4.5:1 body / 3:1 large. Tools:
npm i wcag-contrastfor programmatic, browser DevTools (Chrome and Firefox both report contrast on hover) for ad-hoc. - Use APCA as a sanity check. When WCAG passes but the result looks subjectively weak, APCA usually flags it. APCA is available as
apca-w3(npm) and in dedicated tools (Atmos, Stark plugins).
Both metrics agree on the obvious cases (black text on white is fine; pale grey on white is not). They diverge on the mid-tone and large-text edge cases — exactly where modern design trends like to live.
Concrete recommendations
- Body text: targeting
#1a1a1a(dark grey) on white gives ~17:1 — pleasant, clearly legible. Pure black on white (21:1) can feel harsh; deliberate near-black is fine. - Disabled / placeholder text:WCAG exempts “inactive UI components” from the 4.5:1 rule, but users still need to read placeholders. Target 3:1 minimum.
- Buttons:button text vs button background must hit 4.5:1. Button border vs page background must hit 3:1 (for the “non-text contrast” rule).
- Focus indicators: the focus outline must hit 3:1 against the adjacent background. This is the rule that breaks the most when designers remove default browser focus outlines.
- Dark mode:the WCAG formula is symmetric; numbers translate. But APCA is asymmetric — dark mode tends to need slightly different design tokens than light mode for the same perceived quality. Don’t just invert colours.
What to skip
- Don’t use contrast as the sole signal for state. Error states need contrast andanother cue (an icon, text). Colour-blind users may not distinguish red errors from green successes even at high contrast.
- Don’t target AAA reflexively.WCAG’s own guidance says AAA is “not recommended as a general policy for entire sites” — it’s for specific contexts. AA is the design ceiling for most products.
- Don’t trust auto-generated colour ramps uncritically.An OKLCH ramp with even perceptual steps doesn’t automatically pass WCAG. Verify each adjacent pair.
The pragmatic workflow
At design time: use the WCAG contrast checker in your design tool (Figma, Sketch, Adobe XD all have plugins). Hit 4.5:1 / 3:1 minimums.
At code time: lint your design tokens against WCAG withwcag-contrast or similar. Fail CI on regressions.
At QA time: real screen-reader and keyboard-navigation testing. Contrast is a small slice of accessibility; the keyboard and screen-reader paths are where most a11y bugs actually live.
Worked example: a brand colour that “passes”
Brand teal #3aa6a0 on white background. WCAG contrast: 2.99:1 — fails AA for body text (need 4.5:1) and fails the 3:1 threshold for large text by a hair. APCA score: Lc 52, which APCA rates as “use only for non-content text or above 24px.” Both metrics agree: this teal does not pass as body text on white.
Darkening the teal one step to #2f8682: WCAG 4.52:1 (passes AA body), APCA Lc 67 (passes APCA for large text, marginal for body). One hex-digit change moves the component from failing to passing — and the underlying perceived hue stays recognisably the same teal. Brand colours rarely survive contact with accessibility without a dark-mode variant; build the variant at the same time as the brand palette, not retroactively.
Common mistakes
- Testing only against white. Body text on a coloured panel, button text on a coloured button, link text in a footer with a dark background — each pair needs its own check. A token system that mandates per-pair contrast verification catches what eyeballing misses.
- Ignoring text over images. Hero headlines over photographs almost always fail somewhere on the image. Solutions: a semi-transparent dark overlay beneath the text (drop opacity to 0.4-0.6), a text shadow that creates contrast at the glyph edge, or repositioning the text onto a solid panel.
- Relying on hover states for legibility. Hover styles often improve contrast (darker on hover) — but the resting state is what the user reads. If the resting state fails, the hover doesn’t rescue it.
- Using
rgba()with low alpha for text.Translucent text inherits whatever’s behind it. The computed contrast depends on the background; on a coloured background, alpha < 0.8 almost always fails. Use opaque hex values for text, reserve alpha for decorative chrome. - Treating colour-blind simulation as accessibility testing.Sim tools (Chrome DevTools, Stark) show what a colourblind user sees approximately. They don’t test whether contrast is adequate; they test whether colours are distinguishable. Both checks are needed.
For the underlying colour-space mechanics that the formula linearises, see our CSS color formats guide.
Sources: W3C WCAG 2.1 (2018) and WCAG 2.2 (2023); WCAG 3.0 Working Draft (2024); Andrew Somers, APCA-W3 documentation and supporting user studies; US DOJ ADA Title III web accessibility rule (2024); EU Accessibility Act (Directive 2019/882).
Frequently asked questions
- What contrast ratio does WCAG 2.1 AA require for body text?
- WCAG 2.1 AA requires a 4.5:1 contrast ratio for normal text (below 18 pt / 14 pt bold) and 3:1 for large text (18 pt+ or 14 pt+ bold).
- How do I calculate the contrast ratio between two colours?
- Contrast ratio = (L_lighter + 0.05) / (L_darker + 0.05), where L is relative luminance in linear sRGB. Convert hex to sRGB, linearise using the IEC 61966 gamma, then apply the luminance formula before dividing.
- What is the difference between WCAG AA and AAA contrast levels?
- AA requires 4.5:1 for text (3:1 for large text) and is the legal minimum in most jurisdictions. AAA requires 7:1 for text (4.5:1 for large) and is recommended for critical readability contexts like medical or legal interfaces.
- Does the WCAG contrast formula work for all visual impairments?
- No — the WCAG 2.x formula is based on luminance only and does not account for hue-based colour blindness or low-contrast within similar luminance values. The APCA algorithm (proposed for WCAG 3.0) better correlates with real-world readability.
- Is there a CSS background colour that passes 4.5:1 against both black and white text?
- No single colour achieves 4.5:1 against both simultaneously. Black (#000000) has a ratio of 21:1 against white and 1:1 against itself; you must pick one foreground per background and verify with a contrast checker tool.
- When does the European Accessibility Act require WCAG compliance?
- The European Accessibility Act (Directive 2019/882) required covered digital products and services to meet WCAG 2.1 AA by June 28, 2025, with enforcement applying to new contracts from that date.
Sources & references
Authoritative references cited by this piece. Verified by Buğra Sözeri on the dates shown and re-checked at every deploy.
- W3C WCAG 2.1 — Contrast (Minimum) 1.4.3 / (Enhanced) 1.4.6 — Authoritative source for the 4.5:1 (AA) and 7:1 (AAA) contrast thresholds discussed throughout(as of )
- W3C — Relative luminance and contrast ratio formulas — Mathematical definition of the contrast-ratio formula the article walks through(as of )
- APCA — Accessible Perceptual Contrast Algorithm (WCAG 3.0 candidate) — Reference for the perceptually-uniform contrast algorithm under consideration for WCAG 3(as of )
- IEC 61966-2-1 — sRGB colour space specification — Defines the gamma curve that the contrast calculation linearises before computing luminance(as of )
- European Accessibility Act (Directive 2019/882) — Reference for the EU's 2025 enforcement deadline requiring WCAG-aligned colour contrast in covered products(as of )
- US DOJ — ADA Title III web accessibility rule (2024) — Reference for the 2024 ADA rulemaking that adopted WCAG 2.1 AA as the federal standard cited(as of )
Related
Published May 16, 2026 · Last reviewed May 31, 2026