OKLCH colour tokens: why we moved our palette to OKLCH
OKLCH makes colour ramps predictable: equal steps in lightness look equal. How OKLCH works in CSS, building a ramp with it, and the gamut limit to keep in mind.
Build a palette in HSL and you find that blue at 50% lightness is much darker than yellow at 50%, so every ramp needs hand-tuning. OKLCH is a colour space where lightness means what it looks like. This site's tokens are written in it.
The syntax
--paper: oklch(97% 0.012 85); /* L C H */
--amber: oklch(80% 0.15 75);
--ink: oklch(22% 0.02 260);
--line: oklch(22% 0.02 260 / 0.12); /* with alpha */| Part | Range | Meaning |
|---|---|---|
| L | 0% to 100% | Perceived lightness |
| C | 0 to about 0.37 | Chroma, how colourful |
| H | 0 to 360 | Hue angle |
Ramps that behave
Keep hue and chroma steady and step lightness evenly, and you get a ramp whose steps look even. Two hues at the same L look equally light, so a set of pastels at L 90% sits together without tuning.
--blue-100: oklch(95% 0.03 250);
--blue-300: oklch(85% 0.07 250);
--blue-500: oklch(65% 0.13 250);
--blue-700: oklch(45% 0.12 250);Contrast you can reason about
Because L tracks perceived lightness, the difference in L between text and ground is a good first guide to contrast. It is not the WCAG formula, so still measure, but fixes become obvious: raise L by five and check again. See contrast in a dark UI.
The gamut catch
High chroma values can describe colours an ordinary screen cannot show. Browsers map them into range, which can shift the colour slightly. Keep chroma modest for anything that must look identical everywhere, and check on an sRGB display.
Deriving colours
Relative colour syntax lets you derive a hover state from a token: oklch(from var(--amber) calc(l - 0.05) c h). It is supported in current browsers; keep a plain fallback if you support older ones. The token structure around this is in CSS variables vs a Tailwind theme.
Warm Storefront UI ships this site's full token file in OKLCH: the warm paper and charcoal ramp, five pastels that each carry one meaning, and the amber action colour.
Questions
What is OKLCH?
A colour space written as lightness, chroma and hue, designed so that equal changes in lightness look like equal changes to the eye. In CSS it is written oklch(L C H).
Is OKLCH supported in browsers?
Yes, in all current major browsers. Colours outside a display's range are mapped into it, so check very saturated values on an ordinary sRGB screen.
Why not use HSL?
HSL's lightness does not match what we see: yellow and blue at the same HSL lightness look very different. OKLCH fixes that, so ramps and contrast are more predictable.