Contrast Ratio — AA vs AAA Without Audit Theater
Accessibility contrast is often taught as a single number: “get 4.5:1.” Teams then chase green checkmarks while muted captions, chart legends, and ghost buttons remain hard to read. This piece is the basics with judgment — when AA is enough, when AAA helps, and how to avoid audit theater.
Ratio as a reading condition
Contrast ratio is not a brand emotion; it is a proxy for whether glyphs separate from the background. Low vision, bright rooms, cheap panels, and aging eyes all shrink the usable gap.
Relative luminance(fg) vs Relative luminance(bg) → ratio
Black on white ≈ 21:1
Mid gray on light gray ≈ 3:1 or less
You do not need to compute luminance by hand. You do need to sample the true background (including overlays).
AA and AAA — different jobs
| AA | AAA | |
|---|---|---|
| Normal text | 4.5:1 | 7:1 |
| Large text | 3:1 | 4.5:1 |
| Typical use | Product UI floor | Long reading / stricter policies |
Large text means roughly 18pt regular or 14pt bold (CSS px depends on root sizing — verify computed size). Marketing “large” that is 16px medium weight is still normal text.
Theater patterns to skip
- Screenshot of one hero heading at 7:1 while body stays 3.2:1
- “We ran axe once on the marketing page”
- Disabling rules instead of fixing tokens
- Claiming AAA site-wide while disabled states are unreadable by design
Honest statement for most SaaS: “We target WCAG 2.x AA for text and essential controls.” Then fund the token work.
A minimal practice loop
- List text roles: body, muted, inverse, link, error, placeholder.
- Check each against its backgrounds in light and dark themes with a contrast checker.
- Raise muted text until body-adjacent copy clears AA — or stop using muted for sentences.
- Re-check hover, focus rings, and selected states.
- Add a Storybook or visual regression case for the worst offender.
Non-text UI
Icons that convey state, input borders that define hit areas, and graph lines that encode meaning need attention too (often 3:1 non-text contrast in WCAG 2.1). Pure decoration can be quieter. If removing the color would hide the meaning, contrast matters.
Copy and layout beat hex tweaking alone
Sometimes the fix is not darker gray — it is:
- Larger type for secondary content
- Stronger separation (cards that do not sit on busy photos)
- Visible labels instead of placeholder-only fields
Contrast ratios assume you are measuring the right pair. Fix composition first when text sits on photography.
How to brief design
Ask for token pairs (text-primary on bg-surface) with documented ratios, not isolated brand hexes. Review dark mode as a first-class palette. Prefer failing a pretty mock in critique over failing users in production.
Contrast basics are small: know AA vs AAA, measure real pixels, and refuse checkbox theater. The win is readable product copy in the environments people actually use — not a perfect score on a single empty route.
Build contrast into the design system
The durable fix is tokens with documented ratios, not heroic one-off hex edits before an audit. Pair each text role with allowed backgrounds, bake checks into Storybook or unit tests where feasible, and refuse muted body copy that only looks elegant on calibrated monitors. Train PMs to treat contrast bugs like functional bugs — they block reading. Automation catches some issues; literate tokens prevent most of the rest. Re-audit when marketing ships a new pastel palette; brand refreshes are contrast regression season.