Blog Productivity Tools I Failed 3 Accessibility Audit...
I Failed 3 Accessibility Audits Before Understanding WCAG Contrast (Here's What I Learned)
Productivity Tools Dec 05, 2025 5 min read 222 views

I Failed 3 Accessibility Audits Before Understanding WCAG Contrast (Here's What I Learned)

WCAG contrast requirements sound simple until you're debugging why your #777 gray fails on #fff but passes on #f5f5f5. Here's the practical guide with the math that actually matters.

A
Adrian
Author

Three times I built interfaces that failed accessibility audits. Three times I thought I understood contrast requirements. Three times the auditor sent back a list of failures that made no sense to me.

"Your body text fails AA." But it's dark gray on white, the most readable combination imaginable. "Your links don't have sufficient contrast against surrounding text." They're blue, links are always blue. "Your placeholder text fails." It's supposed to be subtle!

After the third audit, I stopped guessing and learned how contrast ratios actually work. Here's everything I wish I'd known earlier.

The Ratios You Need to Memorize

Developer testing color contrast

WCAG defines specific contrast ratios for different content types. These aren't suggestions - they're pass/fail thresholds.

Content Type AA Ratio AAA Ratio Notes
Normal text 4.5:1 7:1 Under 18pt regular / 14pt bold
Large text 3:1 4.5:1 18pt+ regular / 14pt+ bold
UI components 3:1 - Buttons, form controls, focus indicators
Graphical objects 3:1 - Icons, chart elements, infographics
Incidental / Decorative None None Logos, disabled elements, pure decoration

AA is the standard most requirements cite. AAA is aspirational for most sites but worth targeting where practical.

Why Your "Readable" Gray Probably Fails

This is the trap I fell into. Here's what I learned:

Common Gray Colors on White (#ffffff):

  • ✗ #999999 → 2.85:1 (fails everything)
  • ✗ #888888 → 3.54:1 (fails normal text AA)
  • ✗ #777777 → 4.48:1 (fails normal text AA by 0.02)
  • ✓ #767676 → 4.54:1 (passes normal text AA)
  • ✓ #595959 → 7.0:1 (passes AAA)

#767676 is the lightest gray that passes AA on white. Memorize it. I use it constantly.

The frustrating part: #777777 (which looks nearly identical) fails. You can't eyeball this. You need a tool to check WCAG color contrast ratios before committing to a color palette.

The Link Problem Nobody Explains

Links have a special requirement that most developers miss: if links are only distinguished by color (no underline), the link color needs 3:1 contrast against the surrounding text, IN ADDITION to 4.5:1 against the background.

This is why "just make links blue" fails audits. Standard blue (#0000ff) on black text (#000000) against white:

  • Blue vs white background: 8.59:1 ✓
  • Blue vs black text: 2.4:1 ✗

The link passes against background but fails against surrounding text. Solutions:

  1. Underline links (removes the 3:1 text requirement)
  2. Use a blue with more contrast against black
  3. Use a non-underlined indicator (icon, different font weight) plus color

I now underline all links by default. It's simpler than finding colors that pass both checks.

Testing Your Actual UI

Testing in isolation isn't enough. You need to test colors in context:

Test every state: Normal, hover, focus, active, disabled. I've seen buttons pass in normal state but fail on hover. Each state is a separate check.

Test both themes: If you have dark mode, test contrast in both. White text on dark gray might pass while light gray text doesn't.

Test over variable backgrounds: If text appears over images or gradients, check the worst-case area.

Test at actual sizes: The large text exemption (3:1) only applies at 18pt+. Your "large" heading at 17px needs 4.5:1.

Fixing Failures Without Redesigning

When an audit comes back with failures, here's the minimal-change approach:

Gray text too light: Darken by 10-20% increments until it passes. The visual difference is often imperceptible.

Colored text failing: Shift toward darker variant of the same hue. #3498db failing? Try #2980b9.

Button borders invisible: Increase border darkness or width. A 2px border at 3:1 can look identical to a 1px border at higher contrast.

Placeholder text failing: This is controversial - many designers want subtle placeholders. But they need 4.5:1. Either darken them or reconsider whether you need visible placeholders at all.

Focus indicators weak: Default focus rings are often insufficient. Add a 3px solid outline in a high-contrast color. It's one CSS rule.

Building Accessible Palettes From Scratch

If you're starting a new project, build contrast into your color system:

Define text colors first. Start with your body text color against your background. Get 7:1 if possible (AAA) - it gives you headroom.

Define a "muted" text color. This should still pass 4.5:1. It's for secondary content, timestamps, captions.

Test accent colors immediately. Your brand blue, green, orange - test each against both light and dark backgrounds before falling in love with them.

Create dark variants. Every color needs a darker version for use as text on light backgrounds. Define these in your system.

Document the combinations. "Primary blue is for buttons and large headings only" prevents developers from using it where it fails.

Tools That Actually Help

Manual checking works but doesn't scale. Use these:

Browser extensions: WAVE, axe DevTools, or Lighthouse (built into Chrome) scan entire pages and flag contrast failures with specific locations.

Design tool plugins: Figma's "Contrast" plugin, Stark for Sketch/Figma check as you design rather than after.

Automated CI checks: axe-core, Pa11y, or similar run on every build and catch regressions before they ship.

Quick ratio checks: For spot-checking two colors, use a web-based contrast checker. Enter foreground and background, get immediate pass/fail.

Check Your Site This Week

Run an accessibility audit on your current site. Lighthouse in Chrome DevTools takes 30 seconds. Every contrast failure is an opportunity to improve readability for everyone - not just users with visual impairments.

The rules aren't arbitrary. They exist because the difference between 4.4:1 and 4.6:1 is the difference between readable and not-readable for millions of people. Now you know the numbers. Use them.