Using a Palette
How to take a palette somebody else drew and turn it into something you can ship — and the four jobs it is allowed to do on the way.
Everything below is the real component. Change the controls, tab through it, and turn on Inspector Mode to read any value off the screen.
Every palette in this section, ranked by how many of its twenty colours can carry body text on a white page. Read the first two columns together: every row adds up to exactly twenty, with nothing counted twice, because a colour that clears 4.5:1 on white cannot also clear it on black. Choosing the surface is what splits a palette in two, and not one of these fourteen was drawn expecting you to choose.
| Palette | Colours | Text on white | Text on black | 3:1 on white |
|---|---|---|---|---|
| Dutch Palette | 7 | 13 | 13 | |
| Indian Palette | 6 | 14 | 7 | |
| French Palette | 6 | 14 | 10 | |
| British Palette | 6 | 14 | 12 | |
| Flat UI Palette v1 | 5 | 15 | 11 | |
| Aussie Palette | 5 | 16 | 8 | |
| Russian Palette | 5 | 16 | 10 | |
| Spanish Palette | 5 | 15 | 10 | |
| Swedish Palette | 4 | 16 | 9 | |
| Canadian Palette | 4 | 16 | 8 | |
| Chinese Palette | 4 | 16 | 7 | |
| American Palette | 4 | 16 | 7 | |
| Turkish Palette | 3 | 17 | 7 | |
| German Palette | 3 | 17 | 9 |
Lifting one hue into a ramp
The single most useful thing you can do with a borrowed palette. Take the hue, build ten perceptually even steps, and keep the original value in place at the step it actually lands on — now it is themeable, auditable, and it still looks like the palette you liked.
Why a flat red is not a danger colour
The most common misuse, and the one that reaches production most often, because a red that looks like an error at a glance is very hard to argue with in review.
--flat-us-mint-leaf: #00b894;Not a checklist to run at the end. These are the requirements the component was built from.
Contrast
- The three grades that matter: 4.5:1 for body text, 3:1 for large text and for any graphic or boundary that carries meaning, and nothing at all for pure decoration.
- White and black are the bounds, not the targets. Your real surfaces sit between them, so a colour that scrapes 4.5:1 on white will fail on a card that is not quite white.
- A palette that passes on a dark surface and fails on a light one is not "mostly fine" — it is a palette you can only ship with one theme.
- None of these palettes were designed against a contrast requirement. That is not a criticism of them; it is the reason the audit exists.
Keyboard
| ⌘I | Inspector Mode reports the composited contrast of anything you hover. |
Screen readers
- Nothing on a palette page is announced by its appearance. Every swatch has an accessible name carrying both the colour name and its value.
- If your only distinction between two things is which palette colour they use, they are the same thing to a screen reader.
Focus & touch
- A borrowed palette must never supply the focus ring. The ring has one job — clearing 3:1 against every surface in the system — and it is the one colour that cannot be chosen for how it looks.
- Colour choice does not change hit area, but low-contrast controls are measurably slower to acquire — a target you can barely see is a target you aim at carefully.
| Attribute | Applied to | Notes |
|---|---|---|
| Text alternative | Anything encoded by colour | A chart series, a category tag, a calendar block. Colour distinguishes; it never identifies. |
| prefers-contrast: more | Media query | Users who ask for more contrast are asking you to drop the decorative palette, not to darken it slightly. |
Example usage
The whole conversion, in the order it should happen.
1// 1. Bring it in namespaced. Never --ds-*, which means "certified".2// --flat-us-electron-blue: #0984e3;34// 2. Categorical use is immediate and safe — no colour here means anything.5const SERIES = ['electron-blue', 'mint-leaf', 'pico-8-pink', 'sour-lemon']6 .map((slug) => `var(--flat-us-${slug})`)78// 3. Semantic use is never immediate. Lift the hue, build the ramp,9// then bind the semantic token to a step of YOUR ramp.10// --p-brand-500: #0984e3; <- the borrowed value, now a step11// --ds-accent: var(--p-brand-500);1213// 4. Text on any borrowed fill is measured, not chosen.14import { readableOn } from '@/docs/framework/palette'15<span style={{ background: hex, color: readableOn(hex) }} />CSS
Three tiers, and where a borrowed colour is allowed to enter.
/* Tier 0 — borrowed. Namespaced by source. Read by nothing but tier 1. */
:root {
--flat-us-electron-blue: #0984e3;
}
/* Tier 1 — primitive. Our ramp, built from that hue, evenly spaced. */
:root {
--p-brand-400: #3097e9;
--p-brand-500: var(--flat-us-electron-blue);
--p-brand-600: #0a6cba;
}
/* Tier 2 — semantic. The only tier a component is allowed to read. */
:root {
--ds-accent: var(--p-brand-500);
--ds-accent-text: var(--p-brand-300); /* measured against -subtle */
}
/* What must never happen. */
.button { background: #0984e3; } /* untraceable */
:root { --ds-danger: #ff7675; } /* uncertified */Professional tips
- Judge a palette by its extremes and its greys, not by its most attractive swatch. The attractive swatch is almost always a mid-tone, and mid-tones are the least useful part of any palette.
- If two palettes look interchangeable as strips, they are interchangeable in your product. Pick on the audit numbers instead.
- A palette is a fast way to lose an argument about colour and get on with the layout. That is a legitimate reason to use one.
- Sorting by hue tells you which colours can sit next to each other; sorting by lightness tells you which ones can be read. Both orders are on every palette page.
- Every palette page carries the conversion already done — surfaces, a solved text ramp, semantic roles with hover and active, chart colours and the CSS to paste. Read it as a worked example rather than a deliverable: the rules are consistent across all fourteen precisely so that they are comparable, which is not the same as being right for your product.
Performance
- Twenty custom properties cost nothing. Twenty custom properties defined inside a component that mounts a hundred times cost something — define them once at :root.
- Do not ship all fourteen palettes to the browser. Each page in this section imports only its own, and your product should import only the one it uses.
Common mistakes
- Treating the palette as complete. Twenty values with no neutrals, no ramp and no dark-theme counterpart is a third of a colour system.
- Using palette order as importance order. The designer arranged those twenty for the picture, not for you.
- Assuming a name describes the colour. “Light Red” in one palette is darker than “Pastel Red” in another; the names are memorable, not measured.
- Copying a palette into Figma and into CSS separately. They drift within a sprint.
Real-world recommendations
- Flat UI Colors 2 is the most-used palette collection on the web, which means these colours carry recognition. Using them says "I picked a palette" as clearly as a stock photo says "I picked a stock photo".
- When a stakeholder sends you a palette link, what they usually mean is "the current colours feel wrong". Take that as the brief; the link is a symptom.
- Keep the borrowed tier in your codebase even after you have built ramps from it. It documents where your brand hue came from, and that question gets asked about once a year, forever.