CSS & design

How to Build an Accessible UI Color Palette

Choose and test semantic color pairs for buttons, labels, focus indicators, and dark mode interfaces.

Photorealistic editorial photo for Accessible Color Palettes
CSS & design · Practical ideas for your next build

An accessible palette is a set of working foreground/background combinations. A collection of attractive standalone swatches is not enough. Begin with semantic roles such as page background, body text, muted text, primary button, and error state, then test each role in the context where users will see it.

Create a pair matrix

List the combinations used by components: body text on surface, secondary text on surface, button text on brand, and links within paragraphs. Test each pair with a contrast checker and record its intended use. A brand color that works as a large decorative shape may fail for a small button label. Adjust the label color or choose a darker or lighter brand variant for that role.

Include states and non-color signals

Hover, active, selected, and focus states need separate inspection. Avoid using color alone to explain errors or selection; add text, icons, borders, or another visible cue. Text contrast criteria differ from requirements for user interface components and graphical objects, so do not apply the normal-text threshold indiscriminately to every border. Confirm which requirement fits the element.

Treat dark mode as its own design

Inverting a palette does not preserve all useful relationships. Muted text can become too dim, brand backgrounds can dominate, and disabled states can be confused with active controls. Test both themes independently using real components. Leave some margin above the minimum where practical so minor token changes do not push a combination below its required ratio. Recheck any alpha overlays after compositing them with the actual surface.

Worked example

EXAMPLE
Role                 Foreground   Background
Body text            #111827      #ffffff
Inverse text         #ffffff      #111827

Can I certify a whole palette with one ratio?

No. Contrast belongs to a particular pair in a particular use. Test the combinations your components actually render.

Reference and further reading

Read the official documentation ↗