Color Contrast
Insufficient contrast is the single most common WCAG failure. Check that text, meaningful icons, and the boundaries of interactive controls stand out enough from their background — in every theme and every interactive state.
What to test
- Body text and headings meet the minimum ratio for their size.
- Muted, helper, and placeholder text that still conveys information.
- Meaningful non-text UI: icons, focus rings, form borders, chart lines.
- Text set over images or gradients, where the background varies.
- Every state — hover, focus, active, selected, disabled, and error.
Minimum ratios
- Normal text
- 4.5 : 1
- Large text (≥ 24px, or ≥ 18.66px bold)
- 3 : 1
- Icons & UI component boundaries
- 3 : 1
- Focus indicator vs adjacent colors
- 3 : 1
How to test
- 1Run an automated pass (axe DevTools, Lighthouse) to flag obvious text-contrast failures fast.
- 2Sample real foreground/background pairs with a contrast checker — automation can't judge text over images.
- 3Measure non-text UI (icons, borders, focus rings) against their adjacent color; the threshold is 3:1.
- 4Repeat in both light and dark themes, against the actually-rendered background, not the token value.
Edge cases
Focus indicators
A focus ring is non-text UI, so it needs 3:1 contrast — and against BOTH the adjacent colors it touches: the component's own background AND the page background it overlaps. A ring that only stands out on one side can still fail (1.4.11). WCAG 2.2 adds 2.4.13 Focus Appearance (AAA) with minimum-area and change-of-contrast rules if you're targeting AAA.
Disabled controls are exempt — if truly inactive
Disabled elements have no contrast minimum, but only when they're genuinely non-operable. A control that merely looks disabled yet still works must still pass 4.5:1 / 3:1.
Text over images, video and gradients
Measure the worst-case region of the background, not an average — a caption can pass over the dark part of an image and fail over the light part. Add a scrim, overlay, or text shadow so every pixel behind the text clears the threshold.
Every interactive state
A color that passes at rest can fail on hover, focus, active, selected, or error. Re-measure each state, in both light and dark themes, against the actually-rendered background rather than the design token.
Placeholder and “ghost” text
If placeholder text conveys a requirement or instruction it must meet 4.5:1. Even as a pure hint it should stay legible — very light placeholders are a common failure.
Common failures
- Light-gray placeholder or helper text below 4.5:1.
- Focus rings or input borders too faint to meet 1.4.11.
- A focus ring that contrasts with the button but not the page behind it.
- Accent-colored text placed on a light tint of the same accent.
- White text over the light region of a hero image.