Color

WCAG contrast ratio

A ratio measuring the luminance difference between foreground and background text, from 1:1 (no contrast) to 21:1 (max). WCAG AA requires 4.5:1 for normal text, AAA requires 7:1.

How the ratio is worked out

Every color gets a relative luminance from 0 (black) to 1 (white). The formula weights the channels by how bright each one looks to the eye: 0.2126 for red, 0.7152 for green and 0.0722 for blue. The ratio is the lighter color's luminance plus 0.05, divided by the darker color's luminance plus 0.05. The 0.05 allows for stray ambient light, and it's why black on white tops out at 21:1 instead of running off to infinity.

The ratio only sees luminance, so hue doesn't count. Two colors with the same luminance score 1:1 even if one is red and the other green. Green carries most of the weight, which is why pure yellow and pure blue, both at 50% HSL lightness, act so differently on black. Yellow scores 19.56:1 and blue only 2.44:1.

Which threshold applies

What you're checking sets the number:

  • Normal text needs 4.5:1 for AA (success criterion 1.4.3).
  • Large text needs 3:1 for AA. Large means at least 18 point, or at least 14 point and bold. That's 24 CSS pixels, or 18.7 pixels in bold.
  • Enhanced contrast at AAA (1.4.6) asks for 7:1 for normal text and 4.5:1 for large text.
  • Buttons, input borders, icons and the parts of a chart you need to read must reach 3:1 against the colors next to them (1.4.11, AA).

A few things have no requirement: disabled controls, purely decorative text, text nobody can see, and logos or brand names.

Gray on white, one step at a time

The 4.5:1 line is sharp. On white, #767676 scores 4.54:1 and passes. #777777, one step lighter, scores 4.48:1 and fails. WCAG says a computed ratio must not be rounded up to meet a threshold, so 4.499:1 fails too.

Light gray is the usual culprit. #999999 is popular for captions and placeholders, and it scores 2.85:1 on white. That misses the 3:1 line for large text as well as the 4.5:1 line for normal text.

Colors fail the same way. White text on a medium blue like #3B82F6 scores 3.68:1. That's enough for large text and short of 4.5:1 for body copy. A darker blue, #2563EB, scores 5.17:1 and clears both lines.

Fixing a pair that fails

Change the text color first, and keep the hue so the brand look survives. As the gray steps show, a small shift can be enough.

Text over a photo is harder, because the background changes from pixel to pixel. Put a dark overlay between the two. Over the brightest possible area, white text needs an overlay of at least 54% black to reach 4.5:1. The text over images guide goes through it.

For a whole design, list the text and background pairs you'll actually use and check each one. Three text colors on three backgrounds make 9 pairs. The accessible palette guide shows how to build the set so every pair passes from the start.

One limit to know about: WCAG measures the colors written in your markup and styles, not what one screen happens to show. If a page sets no background, the check assumes white.

Work it out yourselfOpen the Contrast Checker

Sources

Back to the glossary