Snappy ToolsYou've probably seen accessibility audits flag contrast ratio failures. Maybe Lighthouse gives your...
You've probably seen accessibility audits flag contrast ratio failures. Maybe Lighthouse gives your site a poor score, or a design review marks text as "unreadable for low-vision users." But what does a contrast ratio actually measure, and what do the thresholds mean?
Here's the practical explanation — with the math kept simple.
The WCAG contrast ratio compares the relative luminance of two colours: foreground (text) and background. Luminance is a measure of perceived brightness, not just the raw RGB value.
The formula:
contrast ratio = (L1 + 0.05) / (L2 + 0.05)
Where L1 is the lighter of the two luminance values and L2 is the darker. The result is a ratio from 1:1 (no contrast — identical colours) to 21:1 (maximum contrast — pure black on pure white).
Relative luminance for an sRGB colour (r, g, b):
For each channel, first linearise:
if channel <= 0.04045: linear = channel / 12.92
else: linear = ((channel + 0.055) / 1.055) ^ 2.4
L = 0.2126 × R_linear + 0.7152 × G_linear + 0.0722 × B_linear
The linearisation step is what trips people up. Raw hex values are not luminance values. #808080 (mid-grey) has a luminance of approximately 0.216, not 0.5 — the human eye perceives brightness nonlinearly.
WCAG 2.1 defines two conformance levels that affect colour contrast:
Level AA (minimum standard, required for most legal compliance):
Level AAA (enhanced accessibility):
These thresholds account for users with moderately low vision who don't use assistive technology. Level AA is the target for most production web applications.
Placeholder text on inputs
Browsers default to placeholder text at about 40% opacity. Many designers replicate this with color: #999 on a white background, which gives roughly 2.8:1 — well below AA. Fix: use #767676 (color: #767676) for the minimum AA-compliant grey on white.
Light grey text on white
The industry default "muted" colour — #aaa or #999 — fails AA on white backgrounds. A 4.5:1 compliant grey on #fff is at least #767676. Check your card subtitles, helper text, and disabled states.
Coloured buttons
Blue primary buttons often fail when the text is white. #1a73e8 (Google Blue) gives approximately 3.0:1 with white text — passing for large text only. If your button text is small (< 18pt), you need a darker blue.
Brand colour on background
Green (#2f855a — a popular Tailwind green) on white: ~5.1:1. Passes AA. But on a light grey background (#f5f6fa) it drops to ~4.6:1 — still passing, but close. If you lighten the background to #f0f0f0, it fails.
Status badges and tags
Warning yellow is a frequent offender. #fbbf24 on #fff gives roughly 1.7:1. Use #d97706 (amber-600) for the text colour and a light yellow background instead of the reverse.
Decorative icons don't need to meet contrast requirements. But informational icons — icons that convey meaning without accompanying text — do. The threshold is 3:1 against the adjacent background.
If you have an error icon that's #ef4444 on #fff, the contrast is about 4.0:1. Passes for an icon (3:1 threshold). But if the same red is used for small text, it fails (needs 4.5:1). Colour alone shouldn't convey information in any case — pair icons with visible labels where possible.
The fastest approach is a browser DevTools check: inspect an element, go to colour picker, and look for the WCAG AA/AAA badges (Chrome and Firefox both show these inline now).
For a more systematic check — comparing specific hex values, testing a background/text combination across your design system — a standalone tool is faster. I use snappytools.app/color-contrast-checker for this: paste two hex values (or pick with a colour picker), get the ratio, WCAG AA/AAA badge, and an immediate pass/fail. No signup, runs in the browser.
If text fails:
If a UI component fails:
If your brand colour fails:
WCAG 3.0 will replace the current luminance-based ratio with APCA (Advanced Perceptual Contrast Algorithm), which accounts for text size, font weight, and polarity (light-on-dark vs dark-on-light) more accurately. The current 4.5:1 standard can fail in some edge cases (very light backgrounds with mid-grey text) and pass in others where the visual result is borderline.
APCA isn't required yet — WCAG 2.1 is still the legal baseline. But if you're designing a new system, it's worth testing against both.
The takeaway: contrast ratio failures are usually fixable in minutes once you know which elements to check. The three most common culprits — placeholder text, muted body copy, and primary brand colour buttons — cover 80% of the issues in most UI codebases.