A palette
everyone can read.
Most palettes are chosen by eye and then fail an audit six months later. Contrast is not a matter of taste and it is not perceptual brightness, it is a specific ratio you can calculate. Once you know what the number means, building a palette that passes gets much easier.
What the ratio measures
WCAG contrast compares the relative luminance of two colours. Each channel is normalised, linearised through the sRGB transfer curve, then weighted: red 0.2126, green 0.7152, blue 0.0722. The ratio is (L1 + 0.05) / (L2 + 0.05), running from 1:1 for identical colours to 21:1 for black on white.
Those weights are why green carries most of the perceived brightness and blue almost none. A saturated blue and a saturated red can look equally dark and be far apart in luminance, which is the usual reason a pairing fails when it looked fine.
The thresholds
| Rule | Body text | Large text | UI and graphics |
|---|---|---|---|
| AA | 4.5:1 | 3:1 | 3:1 |
| AAA | 7:1 | 4.5:1 | not defined |
Large means at least 24px, or 18.66px if bold. Below that the body threshold applies, and this catches people out constantly: a 20px semibold subheading is body text as far as the rules are concerned.
User interface components count too. Under AA, the border of an input, the edge of a toggle and any icon carrying meaning all need 3:1 against what is behind them. Purely decorative graphics are exempt.
Building a palette that passes
Start from a neutral ramp rather than from your accent. Pick a near-black for text and a near-white for the page, confirm they clear 7:1, and build the greys between them in even luminance steps. That ramp will carry most of your interface.
Then bring in the brand colour and accept that it probably fails as body text. Most brand colours do. The move is not to abandon it but to give it the jobs it can do: large display type, fills behind white or black text, borders, and decorative accents. For links and small text, use a darkened step from the same hue.
Darkening in HSL keeps the hue and drops the lightness, which preserves brand recognition while moving luminance. Two or three steps down is usually enough to clear 4.5:1 on a light page.
A brand colour that fails on white will usually pass as a background with white or near-black text on top. Check both directions before you rule it out.
What the ratio does not cover
Contrast is not the whole of colour accessibility. Around 8 percent of men have some form of colour vision deficiency, most commonly red and green confusion. A pass or fail state signalled only by colour is invisible to them regardless of contrast, which is why WCAG separately requires that colour is never the sole carrier of meaning. Add an icon, a label or a shape.
There is also a newer model, APCA, designed to fix the known weaknesses in the WCAG formula, particularly around very dark backgrounds where the current maths is too lenient. It is not yet a requirement. Design to WCAG, and treat APCA as a second opinion.
Practical checks
- Body text, every size and weight you actually ship.
- Placeholder text, which is usually the lightest thing on the page.
- Disabled states, which are exempt from AA but still need to be legible.
- Text over images, at the worst point of the image, not the average.
- Focus rings, which need 3:1 against both the component and the page.