Curbcut

Color contrast accessibility: fix low text contrast

Last updated

This guide covers color contrast accessibility for text: what fails, who it hurts, how to fix it and how to check the fix. The WCAG 2.2 requirement is Success Criterion 1.4.3 Contrast (Minimum), at level AA [2]. Checkers built on axe-core report it under the rule color-contrast [1].

What is wrong

The text and its background are too close in brightness. WCAG measures this as a contrast ratio. The ratio runs from 1:1, where text and background are the same, to 21:1, black on white [3].

The thresholds are not rounded. A ratio of 4.499:1 does not meet 4.5:1 [2]. For example, #777777 on white measures 4.47:1 and fails. #767676 on white measures 4.54:1 and passes.

Some text has no contrast requirement. This covers text in an inactive control, pure decoration, text nobody can see, text inside a picture with other significant content, and logos [2]. Brand guidelines are not an exception for other text [2].

Icons, form field borders and chart lines fall under a different rule. Success Criterion 1.4.11 Non-text Contrast asks for 3:1 against adjacent colors [5]. This guide is about text.

Who it hurts

People with low vision may not be able to read faint text. The same goes for people with color vision deficiency and anyone reading a screen in bright light [1]. Deque notes that about 8% of men and 0.4% of women in the US cannot see the full range of colors [1].

W3C chose 4.5:1 to make up for the contrast loss that comes with vision of about 20/40. That level of vision is commonly reported for people around age 80 [2]. WCAG computes contrast from luminance, so hue plays almost no part [2]. Two colors that look very different can still fail.

How to fix it

  1. Find the failing text. Run a checker on the rendered page, or measure the two colors with a contrast checker [1].
  2. Note the text size and weight as they render. They decide whether 4.5:1 or 3:1 applies [2].
  3. Darken the text or lighten the background until the ratio is at least 4.5:1, or 3:1 for large text [1]. On a dark theme, do the reverse.
  4. Set both colors. If you set a text color, set a background color too, and the other way round [4]. Otherwise a user's own color settings can produce a pair you never tested.
  5. Check text over images or gradients at its lowest-contrast point. Measure the text against the part of the image that is most like it and sits behind it [6].
  6. Check every state of the text: placeholder text, hover text and focus text all count [2].

Here is the change for gray text on white:

/* Before: 2.32:1 on white, fails for all text sizes */
.note { color: #aaaaaa; background: #ffffff; }

/* After: 4.54:1 on white, passes for all text sizes */
.note { color: #767676; background: #ffffff; }

For large text only, a lighter gray works. #949494 on white measures 3.03:1, which passes the 3:1 limit.

Text over a photo needs a backing that holds up at the photo's lightest spot. W3C describes shading the area behind the letters or adding an outline or halo [7]. A dark backing behind white text works:

.hero-title {
  color: #ffffff;
  background: rgb(0 0 0 / 0.7);
}

Even over a pure white part of the photo, this backing gives white text about 8.5:1.

How to check the fix

Where Curbcut helps

The Curbcut browser extension for Chrome, Edge and Firefox checks the page you are on. For each contrast issue, the report shows the text and background colors as rendered. It also shows the measured ratio and the ratio WCAG asks for at that text size and weight. Then it suggests the nearest text color that passes, with a copy button. For #aaaaaa on white it suggests #767676. The ratio is cut to two decimals and never rounded up. The docs explain the contrast view.

The VS Code extension cannot check contrast in source files, because contrast depends on the rendered page. Use the browser extension for that. The WordPress plugin tests a preview of each post with axe-core from inside the editor.

To find low contrast across many pages, Pro adds a site scan of up to 500 pages, and the web app scans whole sites on a schedule. See pricing.

Automated checks, ours included, find only part of all WCAG failures. Contrast in images, in hover states and over gradients still needs a person. For text alternatives, read WCAG 1.1.1 Non-text Content explained. More fixes are in the guides.

Sources

  1. Color contrast rule (color-contrast), Deque University
  2. Understanding SC 1.4.3 Contrast (Minimum), W3C
  3. WCAG 2.2, definition of contrast ratio, W3C
  4. F24: foreground colors without background colors, W3C
  5. Understanding SC 1.4.11 Non-text Contrast, W3C
  6. F83: background images with too little contrast, W3C
  7. G18: a contrast ratio of at least 4.5:1, W3C