Skip to content
Sheet 01Learn OKLCH

Three numbers.
One of them is the theme.

A colour written in OKLCH answers three separate questions. How light, how colourful, which hue. Change the third and you have a new theme. Change nothing else and the hierarchy survives.

the whole ideaoklch(LCH)

3numbers
1changes per theme
8palettes built on it
0maths required
Sheet 02three questions

The mental model.

Every colour on this page and on the rest of this site is these three numbers. The bands are live and redraw from whatever you set below.

L · lightness

How much light?

Zero is black, one hundred is white. Perceptual rather than mathematical, so fifty actually looks halfway, which is the part HSL gets wrong.

Use it for hierarchy. Contrast is almost entirely a lightness question.

C · chroma

How colourful?

Zero is grey. Around 0.1 to 0.2 is vivid. Push further and the colour leaves what a screen can actually show.

Use it for energy. Hold it steady so no palette shouts louder than another.

H · hue

Which family?

A position on the wheel, zero to three hundred and sixty. The only number that says which colour this is.

Use it for identity. This is the number a theme changes, and the only one.

Sheet 03interactive

Move one at a time.

Drag a slider and watch what changes, and more usefully what does not. The sample is the site’s own components with their role tokens driven by these three numbers.

LightnessL52.0%

Move this and the contrast moves with it. Hue and intensity hold exactly.

ChromaC0.000

More or less intense, at the same weight. Notice the contrast barely moves.

HueH

Sweep this. The identity changes completely and the hierarchy does not move at all.

oklch(52.0% 0.000 0)
Try this

Hold lightness and chroma where they are, then sweep hue end to end. That single drag is what a theme change costs when the ladder is fixed.

accent on surface 3.21teaching estimate · not WCAG
01

Colour should explain the hierarchy before you read a word

One controlled lightness ladder makes emphasis predictable in every theme.

02

One surface, three personas

Analysts, leads and admins reading the same data at different depths.

40%

The number the redesign moved, drawn in whatever you have set.

faster to insight
Sheet 04hsl against oklch

The problem it fixes.

In HSL every colour below says fifty percent lightness. They are not remotely the same brightness, which is why a scale built in HSL has to be corrected by eye, per colour, forever.

HSL · every one at 50% Lwildly uneven
Yellowhsl(55 100% 50%)
Greenhsl(140 100% 50%)
Bluehsl(240 100% 50%)
Pinkhsl(300 100% 50%)

Yellow shouts, blue sinks. The number lied, and any rule you write against it is wrong for most hues.

OKLCH · every one at 72% Leven weight
Yellowoklch(72% 0.16 95)
Greenoklch(72% 0.16 145)
Blueoklch(72% 0.16 255)
Pinkoklch(72% 0.16 325)

Same perceived weight at every hue. Now a rule holds, and one ladder works for the whole wheel.

Sheet 05from your hue

One colour becomes a system.

Take the hue you set above, hold chroma, step lightness. That is a full scale, and the four role tokens under it are all a component ever needs to name.

100L 97
200L 90
300L 80
400L 68
500L 56
600L 44
700L 32
800L 20
Text leadoklch(96.0% 0.008 0)headings and core copy
Text subtleoklch(66.0% 0.020 0)body and support
Accentoklch(52.0% 0.000 0)links, focus, marks
Surfaceoklch(23.0% 0.024 0)cards and panels
Sheet 06the payoff

Dark mode stops being a second design.

Mirror the lightness values around the midpoint and leave hue alone. The identity survives, the relationships survive, and there is no second palette to maintain.

Light
/* hue and chroma unchanged */
--surface: oklch(99% 0.000 0);
--text-lead: oklch(16% 0.000 0);
--text-subtle: oklch(48% 0.000 0);
--accent: oklch(52.0% 0.000 0);
Dark — the same block, lightness mirrored
/* only the L values moved */
--surface: oklch(23% 0.000 0);
--text-lead: oklch(96% 0.000 0);
--text-subtle: oklch(66% 0.000 0);
--accent: oklch(60.0% 0.000 0);
Sheet 07three questions

Check your model.

You understand OKLCH when these three feel obvious rather than clever.

New theme, same hierarchy. Which number changes?

Hue, and only hue. Keep the lightness roles exactly as they are, then tune chroma only if the new hue reads weak or leaves the display gamut. If you find yourself changing lightness, you are rebuilding rather than retheming.

Muted text is too faint. Should I raise chroma?

Almost never. Faintness is a lightness problem, because the gap between the text and its background is too small. Raising chroma makes it more colourful and no more legible, and on a dark ground it usually makes it worse.

Does equal OKLCH lightness guarantee WCAG contrast?

No, and this is the one people get wrong. OKLCH is an authoring model, not a contrast certificate. Perceptual lightness and WCAG relative luminance are different measures, computed differently. The ratio in the lab above is a teaching estimate built from lightness alone, so it tracks the right relationship and is not a pass mark. Test every real text-on-background pair, which is exactly why the palettes page publishes 32 measured pairs per palette instead of asserting that the maths holds.

Now go use it.

8 palettes built on exactly this — the same ladder at 8 hues — with every pair measured and the tokens ready to copy.

Playground · 01 — Palettes ↗