WCAG Contrast Explained (AA vs AAA, When It Matters)
Color contrast determines who can read your interface. This is the WCAG math, the four thresholds, the difference from APCA, and how to actually fix violations.
About 8% of men and 0.5% of women have some form of color vision deficiency. Around 4% of people have low vision. That’s 1 in 8 visitors who might not be able to read your text — not because of font size, but because of contrast. This is what WCAG contrast is, the math behind the thresholds, and how to ship interfaces that work for everyone.
What “contrast” actually means
In WCAG terms, contrast is a number — the ratio between the relative luminance of two colors. 1:1 means identical (white on white). 21:1 is the maximum (pure black on pure white). Everything in between is a gradient of legibility.
Two key clarifications:
- It’s about luminance, not hue. Bright yellow on bright green has low contrast even though the colors look very different. Color-blind users especially feel this — what looks like distinct colors to a typical-vision viewer can be near-identical luminance to someone with deuteranopia.
- It’s about the foreground/background pair, not absolute brightness. Dark text on a slightly-darker background fails. Light text on a slightly-lighter background fails. Brightness alone doesn’t matter; the difference matters.
The four WCAG 2.1 thresholds
WCAG 2.1 §1.4.3 (Contrast Minimum) and §1.4.6 (Enhanced Contrast) define four thresholds:
| Level | Text size | Ratio | Use case |
|---|---|---|---|
| AA Large | 18pt+ regular OR 14pt+ bold | 3:1 | Headings, buttons with large labels |
| AA Normal | Anything smaller | 4.5:1 | Body copy, captions, form labels |
| AAA Large | 18pt+ regular OR 14pt+ bold | 4.5:1 | Stricter standard, often public sector |
| AAA Normal | Anything smaller | 7:1 | Body copy in maximum-accessibility contexts |
The practical floor for any modern site is AA Normal (4.5:1). Anything below is treated as a failure by Lighthouse, Axe, and most contracted accessibility audits. AAA is the polish — aim for AA across the board, then bump body text to AAA where you can.
The “Large” exception exists because larger text is more readable at lower contrast. A 24px headline at 3:1 is reasonable; 12px body copy at 3:1 is not.
The math, in three lines
For two sRGB colors, the WCAG contrast ratio is:
contrast = (L_lighter + 0.05) / (L_darker + 0.05)
Where L is the relative luminance of each color, computed as:
L = 0.2126 × R_linear + 0.7152 × G_linear + 0.0722 × B_linear
And each R_linear, G_linear, B_linear channel is the channel value (0–1) gamma-decoded:
channel_linear = channel ≤ 0.04045
? channel / 12.92
: ((channel + 0.055) / 1.055) ^ 2.4
The +0.05 in the contrast formula prevents division-by-zero when one color is pure black, and slightly compresses the range to make small differences in dark colors more meaningful.
The Color Picker computes all of this live.
Why green is weighted so heavily
Green’s coefficient (0.7152) is more than three times red’s (0.2126) and ten times blue’s (0.0722). The reason: human eyes have far more green-sensitive cones. Pure green looks much brighter than pure blue at the same RGB value. This isn’t a CSS quirk — it’s how vision works.
When “passing” still feels wrong
Here’s the trap. WCAG 2.1’s contrast formula was designed in 2008 with assumptions that don’t fully hold for modern interfaces:
- It treats text as opaque shapes, ignoring font weight and stroke thickness.
- It uses a simple luminance formula, not a perceptual one.
- It doesn’t distinguish dark mode from light mode, even though dark mode generally needs higher contrast for the same readability.
Result: some 4.5:1 combinations look fine on light backgrounds but illegible on dark backgrounds. The math says “pass,” your eyes say “no.”
This is why APCA (Advanced Perceptual Contrast Algorithm), the proposed WCAG 3 contrast metric, exists. It accounts for font weight, dark/light direction, and perceptual brightness. APCA produces different numbers (Lc values) and different recommendations.
As of 2026, APCA is not a WCAG requirement. WCAG 3 is still in draft. For compliance work — government contracts, accessibility lawsuits, audit reports — use WCAG 2.1 ratios. APCA is a nice-to-have polish, not a substitute. The Color Picker shows WCAG 2.1; APCA support is on the roadmap.
How to actually fix contrast violations
You ran an audit. It says your gray secondary text on white background is 3.8:1 (fails AA Normal). Now what?
Step 1: Identify the failure direction
Are you working in:
- Light mode: typically need to darken the text or lighten the background. The text moves toward black; the background already is or near white.
- Dark mode: typically need to lighten the text or darken the background. Text moves toward white; background near black.
Step 2: Find the smallest change that lifts the ratio
Don’t blindly slam text to pure black or pure white. Use OKLCH to bump lightness in even, perceptually uniform steps. Increase L by 5% at a time until the ratio passes. The Color Picker’s WCAG meter updates live.
Step 3: Watch for cascading regressions
Lifting one element’s contrast can break another. Common gotcha: bumping body text contrast then realizing your “muted” caption now reads identical to body text. Use a tiered scale:
/* Light mode example */
--color-fg: #0a0a0a; /* primary text — 18:1 on white */
--color-fg-muted: #525252; /* secondary — 7:1 on white (AAA) */
--color-fg-dim: #737373; /* tertiary — 4.6:1 on white (AA) */
Each tier is distinguishable from the next and meets a contrast bar. Don’t ship a “muted” color that’s below AA Normal.
Step 4: Test with simulators
Real testing > simulators, but simulators catch a lot. Use Chrome DevTools’ “Emulate vision deficiencies” panel or Stark, Polypane, or Sim Daltonism. The most important deficiencies to test:
- Deuteranopia / deuteranomaly — green-blindness (most common, 6% of men)
- Protanopia / protanomaly — red-blindness (2% of men)
- Tritanopia — blue-blindness (rare)
- Achromatopsia — full color blindness (very rare; tests in grayscale)
If your interface conveys meaning through color alone (red error states, green success), it fails for these users regardless of contrast. Add icons, text labels, or patterns.
What WCAG contrast does NOT cover
Contrast is necessary, not sufficient. The full accessibility picture also includes:
- Touch target sizes (WCAG 2.5.5 — 44×44 minimum)
- Focus indicators (WCAG 2.4.7)
- Keyboard navigation (2.1.1)
- Form label association
- ARIA live regions for dynamic content
- Caption and audio description for media
- Heading hierarchy semantic correctness
A site can pass every contrast check and still fail a screen reader user. Treat contrast as table stakes, not the finish line.
A practical checklist
Before shipping any UI:
- All body text passes AA Normal (4.5:1) against its background
- All headings pass at least AA Large (3:1)
- Form labels are at AA Normal
- Placeholder text and disabled states pass AA Normal (often missed — disabled fields often go to 2.5:1)
- Focus rings pass 3:1 against adjacent colors (WCAG 2.2 §1.4.11)
- No information is conveyed by color alone
- Tested in dark mode and light mode separately
- Tested with deuteranopia simulation
This list takes 10 minutes per page in a thorough review and prevents most contrast-related complaints.
Related: which color format makes contrast tweaking easier?
OKLCH. Because it’s perceptually uniform, bumping L by +5% produces an even visual step regardless of hue — so you can compute contrast adjustments programmatically. HSL is mathematically convenient but visually uneven (bumping HSL L from 50% to 60% looks like a different jump for yellow vs blue).
For palette generation in 2026, set up a token system in OKLCH, derive your shade scale from a perceptual lightness ramp, and you’ll get even-feeling contrast across all hues. The Hex / RGB / HSL / OKLCH conversion guide covers the format details.
Bottom line
WCAG contrast is one of the most measurable accessibility metrics — there’s a number, the number passes or fails, you fix what fails. The hard parts are remembering to check, building tooling to check at design time, and not treating “passes” as sufficient when there are visible problems.
If you take one rule away: AA Normal (4.5:1) is the floor. Anything in your interface below that is broken for some real users.
Further reading
- Hex, RGB, HSL, OKLCH: Which to Pick in 2026
- WCAG 2.1 §1.4.3 Contrast Minimum
- APCA documentation — the proposed WCAG 3 successor
- Color Picker tool — live WCAG meter for any color pair
Related posts
- Hex, RGB, HSL, OKLCH: Which to Pick in 2026 — Four CSS color formats, four different audiences. This is what each is good at, …
Related tool
Pick colors, convert hex/RGB/HSL/OKLCH, and check WCAG contrast.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.