sfw/fix
color-contrast high

color-contrast: Elements must meet minimum contrast ratio

Text-to-background contrast falls under the WCAG 2 AA threshold, so low-vision users and anyone in glare can't read it.

What you see

color-contrast: Elements must meet minimum color contrast ratio thresholds
Expected contrast ratio of 4.5:1
Element has insufficient color contrast of 3.1:1 (foreground #999999, background #ffffff, font size 14px)

What’s actually happening

axe-core flags a specific element and prints the measured ratio plus the two colors it sampled. Normal text needs 4.5:1; large text (18.66px bold, or 24px regular and up) and UI components need 3:1. The usual offenders are gray placeholder text, light-gray captions, and white text on a pale brand color. Hover and focus states get missed a lot because the scan only sees the resting state.

Common causes

  • Light gray body or helper text on white, e.g. #999 on #fff, which lands around 2.8:1.
  • Brand color used for text that was chosen for logos, not legibility — fine as a fill, too weak as foreground.
  • White or light text over a photo or gradient where part of the image is bright.
  • A color value pulled from a design token that nobody recomputed after a background change.
  • Disabled-state styling reused for active controls, dragging real text down to disabled-level contrast.

How to fix it

  1. Read the ratio axe gives you and aim past the lineThe violation names both hex values and the measured ratio. Plug them into a checker (WebAIM Contrast Checker, or DevTools' color picker, which draws the AA/AAA lines right on the swatch). Target 4.5:1 for body text, 3:1 for large text and icons. Don't stop at exactly 4.5 — antialiasing eats a little.
  2. Darken the foreground rather than bolding itWeight doesn't change contrast. #767676 on white is the lightest gray that clears 4.5:1; anything lighter fails as normal text. Nudge the text darker (or the background lighter) until the checker passes, then update the design token so it propagates.
  3. Fix text over images with a scrim or text shadowDrop a semi-opaque overlay between image and text (`background: rgba(0,0,0,0.5)`) or add a solid text shadow. Measure against the lightest pixel the text can sit over, not the average, because the worst spot is what fails.
  4. Re-scan focus and hover states explicitlyaxe checks the resting state. Force `:hover`/`:focus` in DevTools (Styles pane, `:hov`) and recheck, since a link that passes at rest can fail on hover. Same for placeholder text — it's a frequent silent failure.

Stop it recurring

Bake contrast tokens into the design system and run axe (or pa11y) in CI so a failing color combination breaks the build, not production.

Related errors