TechCompare LogoTechCompare

How to build an accessible color palette: design tokens that pass WCAG AA from the start

Define your accessible color pairs as design tokens and enforce them in code. A palette with 3 text colors × 3 background colors = 9 validated combinations is more maintainable than ad-hoc color picking. Use CSS custom properties to create semantic color tokens (--color-text-primary, --color-bg-surface) that map to accessible values.

Building an accessible color palette means defining text and background color pairs that pass WCAG AA from the start, rather than retrofitting contrast after design. A systematic approach uses a limited set of foreground colors (typically 2-3 text shades and 1-2 accent colors) paired with carefully chosen background tints.

By TechCompare · Updated

WCAG level
WCAG AA
Minimum contrast (4.5:1+)
Example ratio
17.1:1
#1A1A1A on #FFFFFF
Category
Practical Tips
Accessibility knowledge base

How this is calculated

The practical approach is to define your accessible pairs as design tokens. For light mode: dark text (#1a1a1a to #333333) on light backgrounds (#ffffff to #f5f5f5). For dark mode: light text (#e5e5e5 to #ffffff) on dark backgrounds (#1a1a1a to #2d2d2d). Accent colors (brand blues, greens, reds) are the hardest to make accessible and should only be used on known-safe backgrounds, typically white or very light gray. Use a contrast checker to validate every pair in your token set before implementation.

Verdict

The token pattern starts with two or three text shades (#1a1a1a to #333333 for light mode, #e5e5e5 to #ffffff for dark) paired with two or three background tints (#ffffff to #f5f5f5 for light, #1a1a1a to #2d2d2d for dark), which gives you a 3x3 grid of nine validated pairs covering most UI patterns before you ever add an accent. Map those into CSS custom properties as semantic tokens (--color-text-primary, --color-bg-surface) so the accessibility constraint lives at the token layer and components never reach back to raw hex values. When you need programmatic scales, use OKLCH over HSL, since OKLCH's perceptual uniformity means a 10% lightness step produces a consistent perceived brightness across hues and the accessible ladder stays even, where HSL lightness 50% reads bright for yellow and dark for blue.

More Contrast scenarios

Frequently asked questions

How many colors do I need in an accessible palette?
Start with 2-3 text colors, 2-3 background colors, and 1-2 accent colors. That gives you 6-9 validated text-background combinations, which covers most UI patterns. Add more only when a specific component requires it.
How many text and background colors should a design system have for accessibility?
Start with 2-3 text colors (primary, secondary, tertiary), 2-3 background colors (surface, elevated, inverse), and 1-2 accent colors. That gives you roughly 6-9 validated pairs covering most UI patterns. Add semantic colors (success, warning, error, info) only as needed and validate each against all background colors.
Should I use OKLCH or HSL to generate accessible color scales?
OKLCH is better. Because OKLCH is perceptually uniform, varying L by 10% gives a consistent perceived step across hues, so your accessible color ladder stays consistent. HSL lightness 50% looks very different for yellow versus blue, which makes scaling unpredictable. Use OKLCH for any programmatic palette work.