Building accessible colour palettes from scratch
Contrast ratios, ramps and the one test we run before any colour ships in DrumKit.
Megan Sims

Every colour in DrumKit passes one test before it ships. It isn’t a clever algorithm or an expensive tool. It’s a table of pairs, checked by a person, in both themes. This is how we build a palette that passes it, starting from a single brand colour.
Introduction
Most palettes start with a brand colour someone loves and a handful of tints picked by eye. They look lovely in a moodboard. Then the first form goes live, the grey placeholder text is unreadable on a laptop in the sun, and the error red disappears for anyone with a red-green colour vision deficiency.
Accessibility can’t be sprinkled on at the end. It has to be a property of the palette itself, so that any designer picking any two colours from it is already most of the way to a readable screen.

When we rebuilt DrumKit’s palette in 2024, we gave ourselves one constraint: no colour pair in the product would be chosen by eye alone. Everything below follows from that.
A palette isn’t a set of colours. It’s a set of promises about which colours can sit next to each other.
Contrast ratios, briefly
Contrast ratio compares the relative luminance of two colours on a scale from 1:1, the same colour twice, to 21:1, black on white. The Web Content Accessibility Guidelines set the floor. Body text needs at least 4.5:1 against its background. Large text, 24 pixels and up or about 19 pixels in bold, needs 3:1. So do the parts of a control you need to see to use it, like an input’s border or a checkbox’s outline.
Those numbers are minimums, not targets. We aim for 7:1 on body copy wherever the design allows it, because the people who need contrast most are rarely using the screen we tested on.
Building a ramp
A ramp is one hue in eleven steps, from 25 at its lightest to 950 at its darkest. We build ours in a perceptual colour space, OKLCH, so that each step looks evenly spaced from the one before. In an older space like HSL, a yellow and a blue at the same lightness can differ wildly in how bright they actually look.
The useful property of a well-made ramp is predictability. In DrumKit, any step from 600 up passes 4.5:1 on white, and any step up to 300 passes 4.5:1 on the darkest grey. Designers don’t have to check each pair by hand. They only need to remember which half of the ramp they are in.
- Pick the brand colour and find the step where it naturally sits.
- Fix the lightness of every step first, the same for every hue.
- Adjust chroma per step until the colour stops looking muddy or neon.
- Check the 600 step on white and the 300 step on the darkest grey.

The one test we run
Here it is: every text and icon token is checked against every surface token it is allowed on, in light and dark mode, and the result goes in a table in the library’s documentation. A pair that fails is either fixed or forbidden. There is no third option.
The table has about four hundred rows. A script fills in the ratios, but a person reads every failing row and decides what to do, because some failures only matter in one place and some matter everywhere. That review takes an afternoon, twice a year, and it is the most valuable afternoon our design team spends.
We add one more check that no ratio can catch. Every status colour, whether error, warning or success, always travels with an icon or a word. A colour vision simulator will tell you when red and green look the same, but the fix is never a better red. It is never relying on colour alone.
What’s next?
Start with your text colours. List every one your product uses, list every background it appears on, and check the pairs. Most teams find three or four failures in the first hour, usually a placeholder grey and a disabled state.
If you work in DrumKit, the Contrast Checker plugin reads your tokens and builds the pairs table for you, in both themes. Pin the result to your library’s cover page, where everyone will see it.
In our next post we’ll look at charts, where six colours have to be told apart at a glance and the usual contrast rules only take you halfway.

