ACCESSIBILITY · COLOR SYSTEMS
How to build an accessible color palette without flattening the design
Accessibility does not require turning every interface into black text on white. It requires choosing color roles deliberately, testing the combinations users actually encounter, and leaving enough visual distance for hierarchy and state.
Contrast belongs to a pair, not to a palette
A palette is a collection of possible values. Accessibility is evaluated when those values are assigned to actual foreground and background roles. The same green can be excellent as a large decorative surface, fail as small text on white, and work again as a button background with white text.
That distinction changes the way you should build a system. Do not ask whether five swatches “pass.” Ask which pairs will touch in the interface:
- Primary text on the page background
- Muted text on a card surface
- Button text on the action background
- Input borders against the field and page
- Focus indicators against every adjacent color
- Success, warning, and error content on their corresponding surfaces
A color can belong in an accessible system even when it is not suitable for text. It simply needs an appropriate role and a tested companion color.
Start with semantic roles before collecting swatches
Randomly gathering attractive colors creates a palette. Defining what the interface needs creates a system. Write the role list first so every new color has a reason to exist.
| Role group | Typical tokens | Accessibility question |
|---|---|---|
| Surfaces | Page, card, inset, overlay, inverse | Can users distinguish layers and boundaries? |
| Text | Primary, secondary, muted, inverse, link | Does every text role meet the correct threshold? |
| Actions | Primary, secondary, hover, active, disabled | Are labels and states identifiable in every state? |
| Boundaries | Subtle, default, strong, focus | Are required controls and focus cues visible? |
| Semantic | Success, warning, error, information | Is meaning also communicated with text or icons? |
This role-first approach prevents a common failure: choosing five equally strong colors, then discovering that none of them can support quiet surfaces, secondary text, or a clear primary action.
Choose light and dark anchors first
Most interface systems become easier to build once you have dependable light and dark anchors. These are not necessarily pure white and pure black. They are the values that support the most important text and surface pairings.
For a light theme
Choose a page surface, a raised surface, primary text, and a muted text color. Test primary and muted text on both surfaces. If muted text only barely passes, it will become fragile when type size, weight, opacity, or an alternate background changes.
For a dark theme
Do not simply invert the light theme. Very bright text on a pure black background can feel harsh, while low-contrast gray text can become unreadable. Build the dark surface hierarchy independently and test every text role again.
Design complete states, not one attractive button
A primary action is not one color. It is a family of states that must remain identifiable and consistent.
- Default: clear emphasis and readable label
- Hover: visible change without losing text contrast
- Active: stronger pressed feedback
- Focus: a distinct indicator visible against adjacent colors
- Disabled: understandable as unavailable without disappearing
- Loading: recognizable even when the label or icon changes
Many systems fail because the default button passes but the hover shade becomes too close to the surface, the disabled label becomes illegible, or the focus ring disappears against one of the surrounding backgrounds.
Use a contrast matrix to find useful relationships
A matrix compares every color against every other color. It quickly reveals which swatches can serve as text/background pairs, which are too similar for adjacent states, and which need a dedicated companion.
The matrix is especially useful after generating a harmony. A mathematically related palette may look cohesive while containing very few accessible text pairs. That is not a reason to discard it; it is a reason to assign the brighter or more saturated colors to accents and use stronger anchors for text.
Do not communicate meaning with color alone
Contrast solves visibility. It does not solve interpretation. A red border and green border may both be visible but still fail users who cannot distinguish the hues or who do not know what the colors mean.
Pair color with another cue:
- A text label such as “Error” or “Complete”
- An icon with an accessible name
- A pattern or shape in data visualization
- An underline or weight change for links
- A position or grouping change that does not depend on hue
This is why semantic colors should be designed as complete components, not as isolated swatches. An error system includes an icon, heading, message, border, surface, and action—not just a shade of red.
A practical accessible-palette workflow
- List the roles.Define the surfaces, text, actions, boundaries, and semantic states the product actually needs.
- Choose reliable anchors.Establish light and dark values that support primary content.
- Add the brand or accent color.Decide where it can be a surface, where it can be text, and which companion text it requires.
- Generate supporting colors.Use harmony and tonal variation for exploration, then assign roles deliberately.
- Build state families.Create hover, active, focus, disabled, and semantic states before the palette feels finished.
- Run the matrix.Identify strong pairs and near-duplicates.
- Test actual components.Check body copy, small labels, links, controls, borders, icons, charts, and overlays.
- Test both themes separately.Do not assume a reversed light palette creates a usable dark theme.
- Export semantic tokens.Move purpose-based names into design and code.
Final review checklist
- Every color has a defined role.
- Primary and muted text are tested on every surface they can touch.
- Large-text thresholds are used only when the rendered size and weight qualify.
- Controls, borders, icons, charts, and focus indicators are reviewed separately.
- Hover, active, selected, disabled, loading, error, and focus states are complete.
- Transparent colors are tested after compositing.
- Color is never the only cue for meaning.
- Dark and light themes are tested independently.
- Token names describe purpose rather than appearance.
- The design is checked at zoom, on mobile, and under less-than-ideal viewing conditions.
Standards and further reading
Review the W3C guidance for minimum text contrast, non-text contrast, and use of color. HexCheck’s user guide explains how those requirements map to the tools.
GO DEEPER
The color science behind accessibility and perceptual color differences.
Go beyond pass/fail ratios into visible difference, spatial perception, and the appearance effects that influence real interface hierarchy.