Skip to content

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.

Live preview

Everything below is the real component. Change the controls, tab through it, and turn on Inspector Mode to read any value off the screen.

Fourteen palettes, measured

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.

PaletteColoursText on whiteText on black3:1 on white
Dutch Palette71313
Indian Palette6147
French Palette61410
British Palette61412
Flat UI Palette v151511
Aussie Palette5168
Russian Palette51610
Spanish Palette51510
Swedish Palette4169
Canadian Palette4168
Chinese Palette4167
American Palette4167
Turkish Palette3177
German Palette3179

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.

What you were given — one valueElectron Blue #0984e3
What you need — ten, evenly spaced, with the original still in it50100200300400500600700800900

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.

Our danger family

Payment declined

Certified pair. Passes in both themes, and the tint composites over any surface.
Pink Glamour borrowed as “danger”

Payment declined

White on #ff7675 is 2.59:1. It is a lovely colour and it fails.

A palette carries a date

The 2013 original beside a 2019 contribution. Neither is better; they are from different years, and a palette will put a date on your product whether or not you intended one.

Flat UI Palette v1
American Palette

Do

--flat-us-mint-leaf: #00b894;
Put every borrowed value behind a namespaced custom propertyA hex in a component is invisible to theming, to the contrast audit and to search. A namespace — --flat-us-* rather than --ds-* — also stops a borrowed value from ever being mistaken for a certified one.
Text 4.5:1Large 3:1Fill only
Measure before you use, not after reviewEvery palette page in this section carries the audit table. It takes ten seconds to find out that the colour you liked is a fill, and it takes a release to find out the same thing from a user.
Keep the namesWet Asphalt and Jigglypuff are terrible token names and perfect citations. Renaming them to blue-700 and pink-300 severs the link to where they came from, and the next person cannot check your work.
Use the ends, ignore the middleAlmost every palette here is drawn around its mid-tones, which is exactly the region that cannot hold text on either surface. The darkest and lightest members are where the usable contrast is.

Don't

Do not adopt twenty colours because you liked oneA palette arrives as a set and gets used as a set. If you needed one teal, take the teal — importing the other nineteen guarantees that some of them end up on a screen, chosen for availability rather than for meaning.
Do not map a palette onto semantic rolesSuccess, warning, danger and info are contracts about contrast and redundancy, not slots waiting for a green, an amber, a red and a blue. Filling them from a decorative set breaks the contract while looking like it kept it.
Do not let it become a second neutral rampMost palettes here ship two or three greys. They will not match the neutral ramp, they will not be evenly spaced, and once both are in the codebase every border in the product is a coin flip.
Do not use one for data and status at onceThe moment a chart series is coloured with the same red that means "failed", every red mark on the screen reads as an alarm. Categorical colour and status colour must come from different sets.

Accessibility

Not a checklist to run at the end. These are the requirements the component was built from.

1.4.1Use of ColorA1.4.3Contrast (Minimum)AA1.4.11Non-text ContrastAA

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

⌘IInspector 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.
AttributeApplied toNotes
Text alternativeAnything encoded by colourA chart series, a category tag, a calendar block. Colour distinguishes; it never identifies.
prefers-contrast: moreMedia queryUsers who ask for more contrast are asking you to drop the decorative palette, not to darken it slightly.

Code

Example usage

The whole conversion, in the order it should happen.

tsx
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.

css
/* 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  */

Notes

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.