ColorSense Blog
WCAG Contrast Ratios Explained — AA vs AAA for Web Designers
What contrast ratio numbers mean, the difference between AA and AAA, and how to fix a failing color pair without losing your brand identity.
You've designed a beautiful landing page. The brand colors are on point, the typography is clean, the hero looks like it belongs in a portfolio. Then someone runs a Lighthouse audit and your accessibility score is 78. The biggest red flag: insufficient color contrast.
If you've ever stared at a WCAG contrast warning and wondered what "4.5:1" actually means, why "AAA" exists when "AA" already passes, or how to fix a failing pair without throwing away your brand colors — this guide is for you.
What WCAG Contrast Actually Measures
WCAG (Web Content Accessibility Guidelines) is the international standard for accessible web content, maintained by the W3C. The contrast guideline exists for one reason: text needs to be legible to people with low vision, color blindness, age-related vision loss, or anyone reading on a sun-glared phone screen.
The contrast ratio is a single number that compares the relative luminance (perceived brightness) of two colors. The formula is:
(L1 + 0.05) / (L2 + 0.05)
…where L1 is the lighter color's luminance and L2 is the darker. The result ranges from 1:1 (identical colors — totally invisible) up to 21:1 (pure black on pure white — maximum legibility).
You don't need to calculate it by hand. Every modern browser DevTools, Figma plugin, and accessibility tool will compute it for you. What matters is knowing what number to aim for.
The AA vs AAA Targets, in Plain English
WCAG defines two compliance levels for contrast: Level AA (the standard most regulations require) and Level AAA (the enhanced level for sensitive content). Here's the cheat sheet:
- AA — Normal text: minimum 4.5:1
- AA — Large text (18pt+ regular, or 14pt+ bold): minimum 3:1
- AA — UI components & graphical objects (icons, form borders, focus rings): minimum 3:1
- AAA — Normal text: minimum 7:1
- AAA — Large text: minimum 4.5:1
That's the whole spec. Three numbers — 3, 4.5, and 7 — and a definition of "large." Memorise those and you'll know whether any pair of colors passes without opening a tool.
When You Need AA vs When You Need AAA
The honest answer most accessibility consultants will give you: aim for AA on everything, push to AAA where it costs you nothing.
AA is the legal floor. The ADA in the US, the European Accessibility Act, the UK Equality Act, AODA in Ontario, and most public-sector procurement rules all reference WCAG 2.1 Level AA as the compliance benchmark. If you're shipping a commercial product, AA isn't aspirational — it's the bar you have to clear.
AAA is the enhanced level for content where legibility is non-negotiable: medical information, financial disclosures, government services, content for older audiences, and any product whose user base skews toward vision impairment. WCAG itself notes that AAA is not realistic for entire interfaces — some color combinations fundamentally cannot reach 7:1 without losing all brand identity. Use AAA on body copy, calls-to-action, and error messages. Allow AA on decorative or supporting text.
The pragmatic rule: body text and CTAs at AAA, secondary UI at AA, decorative elements at 3:1 minimum.
What "Large Text" Actually Means
The large-text exception is the most-misunderstood part of WCAG contrast. Designers see "3:1 for large text" and assume any heading qualifies. It doesn't.
WCAG defines "large" specifically:
- 18pt or larger at regular weight (roughly 24px in CSS at default zoom), OR
- 14pt or larger at bold weight (roughly 18.66px in CSS)
That's it. A 16px paragraph in semibold is not large text and needs the full 4.5:1. Your H3 in 20px regular weight is not large text and needs the full 4.5:1. The "large text" lane is genuinely for big display headings — hero copy, section titles, marketing splash text.
This trips up so many designers that I'd treat it as a default rule: assume the text on your page needs 4.5:1 unless it's clearly oversized hero copy. You'll be wrong less often.
The Common Failures (and Why They Happen)
The same handful of color mistakes show up in almost every audit:
- Light grey body text on white.
#999999 on #FFFFFF is 2.85:1 — a fail at every level. Designers love it because it looks "soft and modern." It's also unreadable for a meaningful chunk of your audience. Move to #666666 (5.74:1) or darker for body copy.
- Brand-color buttons on a pale tint of the same brand. A teal button (
#22D3EE) on a teal-50 background (#ECFEFF) reads as 1.4:1 — invisible. Tinted backgrounds always need a much darker accent.
- White text on yellow / orange / lime CTAs. Bright warm colors have very high luminance, so white drops to ~2:1. Switch to dark text on bright CTAs and the contrast jumps to 10:1+.
- Placeholder text in form inputs. Almost every design system ships placeholders at
#A0A0A0 or lighter on white — a clean fail. Push placeholder text to #595959 minimum.
- Disabled-state buttons. WCAG explicitly exempts disabled controls from the 3:1 rule. They can be as light as you like. The catch: don't use the same low-contrast styling on enabled-but-secondary buttons. If it looks disabled, users won't click it.
How to Check a Pair in Under 10 Seconds
You don't need a long workflow. Open the ColorSense WCAG Contrast Checker, paste your foreground HEX in one field and your background HEX in the other. You'll see:
- The exact contrast ratio (e.g.
4.62:1)
- AA pass/fail for normal text
- AA pass/fail for large text
- AAA pass/fail for normal text
- AAA pass/fail for large text
- A live preview at body and heading sizes so you can see what readers actually see
If the pair fails, the checker also offers a one-click "Fix it" panel: it walks the lightness in HSL (keeping your hue and saturation intact) until the pair clears your target ratio, and offers two options — adjust the foreground or adjust the background. You keep the brand color's identity; only the brightness moves. That's almost always the right trade-off.
Try it now
Check any color pair against WCAG — free, no signup
Pick a foreground and background, see the exact contrast ratio plus AA/AAA verdicts for normal and large text. One click auto-fixes a failing pair while keeping your hue.
Open WCAG Contrast Checker →
Fixing a Failing Pair Without Losing Your Brand
The instinct most designers have when a brand color fails contrast is to either (a) ship it anyway and hope nobody notices or (b) replace the brand color with a darker shade and lose the visual identity. There's a third option: shift only the lightness, keep the hue and saturation.
Color is three-dimensional. When you express it in HSL — Hue, Saturation, Lightness — you can adjust just one axis at a time. Shifting lightness by 10–20 points usually clears a contrast failure while leaving the color recognisably the same. A "soft mint" at hsl(160, 60%, 75%) doesn't pass on white, but hsl(160, 60%, 35%) does — and it's still recognisably mint.
The key insight: your "brand color" is really a hue family, not a single HEX. Lock the hue, shift the lightness for accessibility-critical surfaces (text, CTAs, focus rings), and use the lighter brand shade where it doesn't have to carry contrast (decorative blocks, hero backgrounds, illustration accents).
Beyond Text: Non-Text Contrast (the Often-Skipped Rule)
WCAG 2.1 added a guideline most designers ignore: 1.4.11 Non-text Contrast. UI components and meaningful graphics also need 3:1 contrast against their adjacent colors. This includes:
- Form input borders against the page background
- Toggle/switch states (the off state versus the on state)
- Focus rings around interactive elements
- Icon-only buttons against their background
- Chart elements that convey data (bars, lines, slice borders)
This is why pale grey form borders (#E5E7EB on white = 1.3:1) technically fail WCAG even though the text inside passes. If a sighted user with low vision can't see where the input field begins, they can't fill it in.
Auditing a Whole Palette at Once
Checking pairs one at a time works for a single landing page. For a full brand palette — five colors plus white and black, that's 21 possible pairings — you need a different tool. The ColorSense Palette Health page scores any palette across every meaningful pair and surfaces the worst offender at the top. From there you can deep-link into the WCAG Contrast Checker pre-loaded with the failing pair and fix it in two clicks.
Practically, this means: when you finalise a brand palette, run it through Palette Health before you ship the design system. Catching a failing color combination at the palette stage saves you from rebuilding components later when accessibility audits come back red.
What to Audit on an Existing Site
If you're auditing a site you've already shipped, prioritise in this order:
- Body copy on every page background variant. This is 80% of the words on your site. Get this right first.
- Primary and secondary CTAs. Both the button background-on-page and the text-on-button.
- Form inputs: placeholder text, label text, helper text, error text, and the input border itself.
- Navigation links: default state, hover state, and active state.
- Icon-only controls: close buttons, social icons, search icon. Often invisible on light backgrounds.
- Data visualisations: chart axes, gridlines, legend text, slice borders.
You'll typically find that fixing the top 5–10 offenders moves your accessibility audit from "concerning" to "compliant" without touching the rest of the design.
Common Misconceptions to Drop
- "It looks fine on my monitor." Your monitor is calibrated, your eyes are healthy, and you're sitting in even office light. Your users are on phones in sunlight, on cheap displays, with mild colour blindness, after 14 hours of screen time. Optimise for them.
- "AAA is overkill." AAA on body copy adds zero design cost — it just means body text is closer to charcoal than to grey. Your designs won't look worse; they'll look more confident.
- "Brand guidelines override accessibility." No regulation in any major market accepts brand consistency as a defence against an accessibility complaint. Brand colors that fail contrast must be paired with accessible alternatives for text-bearing surfaces.
- "Dark mode is automatically more accessible." It isn't. Light text on dark backgrounds has its own contrast hazards (grey-on-grey is just as bad as the inverse). Run the same checks on every dark-mode pair.
Putting It All Together
WCAG contrast doesn't have to be a compliance chore. Three rules cover almost every practical case:
- Aim for 4.5:1 on every piece of text by default.
- Push to 7:1 on body copy and primary CTAs — it costs nothing and improves readability for everyone.
- Hold the line at 3:1 for UI elements that aren't text (borders, icons, focus rings).
When a brand color fails, shift lightness in HSL — don't abandon the hue. When you're auditing a whole palette, score the matrix once with Palette Health and fix the worst offenders first. And when in doubt, drop the pair into the WCAG Contrast Checker and let the "Fix it" panel propose the smallest tweak that gets you there.
Accessibility done right is invisible. The result is a site that's easier to read for everyone — including the version of you that's tired, on a bus, in glare, at midnight. That's the whole point of the standard.
Take it further
Turn any palette into a full brand kit
ColorSense AI Brand Kit pairs your palette with matching fonts, accessibility checks, and export-ready CSS, Tailwind, and Figma tokens.
Build a Brand Kit →