What WCAG asks for
Success criterion 1.4.3 sets a minimum contrast ratio between text and its background:
| Text | Minimum ratio |
|---|---|
| Normal text | 4.5:1 |
| Large text (24 px and up, or 18.66 px bold and up) | 3:1 |
The ratio goes from 1:1 (white on white) to 21:1 (black on white). Logos and purely decorative text are exempt, and so is text on a disabled control. A related criterion, 1.4.11 Non-text Contrast, asks for 3:1 on the borders of form fields, icons and focus indicators.
Why it matters
Around one in twelve men has some form of color vision deficiency, and contrast sensitivity drops for everyone with age. Low contrast is also a problem for people without any disability: a phone screen outdoors, a cheap laptop panel or a dimmed display all make light gray text disappear.
Contrast is usually a design system problem, not a one-off bug. If the gray used for body text fails, it fails on every page, which is why it often shows up with dozens of affected elements in a single report.
Where it usually goes wrong
- Light gray body text.
#999on white is 2.8:1. It looks elegant in a mockup and fails in real life. - Placeholder text used as a label. Browsers render placeholders in a light gray that rarely passes.
- White text on a brand color. Many oranges, yellows, light greens and sky blues can not hold white text at 4.5:1.
- Text over images or video. The ratio changes with every part of the picture. A dark overlay or a solid background behind the text fixes it.
- Links that are only a slightly different color from the surrounding text, with no underline.
- Hover and focus states that lighten the text instead of darkening it.
How to fix it
Pick a darker shade instead of redesigning. Most failures are fixed by moving one step darker on the same hue:
/* Before: 2.8:1 on white */
.muted { color: #999999; }
/* After: 4.5:1 on white, same look */
.muted { color: #767676; }
/* White text on a light brand blue fails, so darken the button */
.button {
background: #1f5fbf; /* 6:1 with white text */
color: #ffffff;
}
For text over a photo, add a scrim so the ratio no longer depends on the image:
.hero {
background:
linear-gradient(rgb(0 0 0 / 0.55), rgb(0 0 0 / 0.55)),
url("/img/office.jpg") center / cover;
color: #ffffff;
}
Fix the color tokens in your theme or design system first (body text, muted text, links, buttons, placeholders), then re-check. One change to a variable can clear hundreds of elements at once.
How to check it
- Run an automated check: contrast is one of the things software measures reliably, element by element.
- In Chrome DevTools, inspect a text element and open the color picker: it shows the ratio and whether it passes AA.
- For text on gradients or images, automated tools may report "needs review". Check the lightest part of the background by hand.
What automated checks miss
Software can not always work out the real background behind text: pseudo-elements, background images and overlapping layers can hide it. It also can not judge whether information is conveyed by color alone (criterion 1.4.1), such as a form error shown only as a red border. That part needs a person.
Last updated October 18, 2026.