Insufficient text color contrast (WCAG 1.4.3)
Text-to-background contrast falls below 4.5:1 (or 3:1 for large text), failing the axe-core color-contrast check.
What you see
Elements must meet minimum color contrast ratio thresholds (color-contrast) Fix any of the following: Element has insufficient color contrast of 2.74 (foreground color: #999999, background color: #ffffff, font size: 12.0pt, font weight: normal). Expected contrast ratio of 4.5:1
What’s actually happening
Light-gray-on-white body text, pale links, or low-contrast button labels that are legible to you but hard to read for low-vision users or anyone in bright sunlight. The automated finding comes from the axe-core 'color-contrast' rule (used by Lighthouse, axe DevTools, WAVE, and most scanners) and reports the exact foreground/background hex, the font size and weight, and the measured ratio versus the required one. This is the single most common accessibility failure: 83.9% of home pages in the February 2026 WebAIM Million had it.
Common causes
- Light gray body text on white, such as #999 on #fff at 2.74:1, a default many themes ship with.
- Brand-colored buttons or links where the text color was never checked against the fill (e.g. white text on a light blue or yellow).
- Placeholder text and form hints in faint gray that fall well under 4.5:1.
- Text laid over a photo or gradient where the underlying pixels vary and parts drop below threshold.
- Theme or design-system color tokens chosen for looks without ever running a contrast check.
How to fix it
- Get the real ratio, don't eyeball itUse the WebAIM Contrast Checker or browser DevTools (Chrome shows a contrast ratio with a pass/fail checkmark in the color picker and the Inspect tooltip). You need 4.5:1 for normal text and 3:1 for large text, where large is 18pt/24px, or 14pt bold/19px and up.
- Darken the foreground or lighten nothing criticalNudge gray text darker until it passes, e.g. #767676 on white is exactly 4.54:1 and is the lightest gray that passes for body text. Fix it in your CSS variables/design tokens so every instance updates at once rather than patching one element.
- Fix text over images with a scrimFor text on photos or gradients, add a semi-transparent dark overlay, a text-shadow, or a solid backing behind the text so the effective contrast clears 4.5:1 at every point, not just on average.
- Don't forget placeholders, focus, and hover statesPlaceholder text, visited/hover link colors, and disabled-looking-but-active controls all get scanned. Walk each interactive state and re-check, since fixing the default color often leaves :hover or :focus still failing.
- Re-scan after changesRun axe DevTools or Lighthouse again on the updated pages to confirm the color-contrast violations are gone. Note scanners skip text over background images, so spot-check those by eye and with a manual sample.
Stop it recurring
Bake 4.5:1 minimum contrast into your design tokens and check every text/background and interactive-state pairing before it ships.