Skip to content
← All guides

Creating Accessible Color Palettes

Accessibility is not a property of a palette — it is a property of each pair you actually put on screen. A palette cannot pass or fail on its own, which is why the work is in deciding which combinations you will use and then testing those.

Open the Contrast Checker

The thresholds, precisely

WCAG 2.1 AA asks for 4.5:1 for body text, 3:1 for large text (roughly 24px, or 19px bold), and 3:1 for interface components and their borders. AAA raises body text to 7:1. Most teams target AA and treat AAA as a goal for long-form reading.

Test pairs, not swatches

List the combinations your interface really uses — body on background, body on surface, muted text on surface, white on primary, primary on background for links — and check each one. That list is usually shorter than people expect, and it is the whole job.

Fixing a failing colour without losing it

When a brand colour fails as text, do not abandon it. Keep it for large headings, buttons and accents where the 3:1 threshold applies, and derive a darker variant for body text. Adjusting lightness in OKLCH gets you there without shifting the hue away from the brand.

Step by step

  1. Write down every text-on-background pair your UI actually renders.
  2. Check each pair and note the ratio, not just pass or fail — it tells you how much headroom you have.
  3. For failures, adjust lightness first; change hue only as a last resort.
  4. Re-check in dark mode, where the same pairs behave differently.
  5. Keep the passing values as named tokens so the next person inherits the decisions.

Frequently asked questions

Does a 4.5:1 ratio guarantee the text is readable?

No — it is a floor, not a guarantee. Thin weights, small sizes, low-quality screens and bright environments all reduce real-world legibility. Treat the ratio as necessary but not sufficient, and look at the result.

Do disabled buttons need to meet contrast requirements?

WCAG exempts inactive controls from the contrast minimum. That said, a disabled state nobody can read is still a usability problem — keep it visibly muted but legible.

Is it enough to check only black and white against my colour?

It is a good first filter — it tells you whether a colour works as a background for text at all — but you still have to test the actual pairs, including muted text and colour-on-colour combinations.

✓ Copied