Colour contrast failures are the most common accessibility audit finding. They hit two groups hardest: low-vision users who can't distinguish low-contrast text, and anyone reading on a bright screen in sunlight. WCAG sets specific ratios: 4.5:1 for normal text, 3:1 for large text, 3:1 for UI components. The fix is rarely per-element — it's at the design-token level where one colour change cascades site-wide.
| Content | WCAG AA | WCAG AAA |
|---|---|---|
| Body text (under 18pt or under 14pt bold) | 4.5:1 | 7:1 |
| Large text (18pt+ or 14pt+ bold) | 3:1 | 4.5:1 |
| UI components (input borders, icons) | 3:1 | 3:1 (no AAA level defined) |
| Focus indicators | 3:1 | 3:1 |
| Decorative / disabled elements | No requirement | No requirement |
Most-common failure. Marketing copy "softening" text to #999 or #aaa fails AA badly.
/* FAIL — #999 on #fff = 2.85:1 */
.muted { color: #999; }
/* PASS — #767676 on #fff = 4.54:1 */
.muted { color: #767676; }
Many brand colours are designed for impact, not legibility. Light blues, pastels, vibrant pinks often fail.
/* FAIL — #4da6ff on #fff = 2.6:1 */
a { color: #4da6ff; }
/* PASS — #1e6fcc on #fff = 5.1:1 */
a { color: #1e6fcc; }
If your brand colour fails, define an "accessible variant" that's a darker shade for text use while keeping the brand colour for backgrounds and large headings.
Default browser placeholder colour is often around #a0a0a0 — fails AA. Override:
::placeholder { color: #6b6b6b; opacity: 1; }
Common pattern: #e0e0e0 border on #fff background. Contrast 1.4:1 — fails the 3:1 requirement for UI components.
input { border: 1px solid #767676; } /* 4.5:1 — passes both 3:1 and 4.5:1 */
/* CSS variables */
:root {
--text-muted: #999; /* failing */
}
/* Tailwind config */
colors: {
gray: { 400: '#9ca3af' } /* used as text-gray-400 */
}
:root {
--text-muted: #6b6b6b; /* now 5.7:1 on white */
}
Every usage of var(--text-muted) across the site now passes contrast. One change, site-wide fix.
webaim.org/resources/contrastchecker — paste foreground and background, get ratio + AA/AAA pass-fail per text size.
Inspect any element → Styles panel → click the colour swatch next to color → contrast ratio shows in the colour picker, with the AA threshold line drawn on the colour gradient.
WAVE, axe DevTools, Stark — all overlay contrast warnings on the live page so you can spot issues during development.
:root {
--bg: #ffffff;
--text: #1a1a1a;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #ffffff; /* keep high contrast in dark mode too */
}
}
pa11y, axe-core CLI, Lighthouse CI. Run against staging URLs, fail builds on new contrast violations.
# GitHub Actions - name: Accessibility check run: npx pa11y https://staging.yourdomain.com --threshold 0
Verify contrast findings are cleared after token fixes.
Run Accessibility Audit →