A way of writing colours as lightness, chroma and hue that tracks how different the colours look more evenly than HSL.
The cylindrical form of OKLab, a perceptual colour space published by Björn Ottosson in 2020 and adopted in CSS Color Level 4 as oklch(). Equal steps in L look like roughly equal steps in lightness across hues, unlike HSL.
OKLCH can describe colours outside any screen's gamut; a browser has to map them in, so an oklch() value is not a promise of what will display.
oklch(70% 0.15 145) is a mid green whose lightness matches oklch(70% 0.15 30) far more closely than the HSL equivalents would.
It makes building even colour scales, themes and accessible palettes far more predictable.
OKLCH is calculated, not measured. A colour's XYZ values are converted to a cone-like response, each component is cube-rooted, and a second matrix gives OKLab's L, a and b; chroma is then the length of (a, b) and hue its angle. In CSS, L runs from 0 to 1, chroma from 0 with no fixed ceiling (a percentage of 100% is defined as 0.4), and hue in degrees. The matrices were fitted by Björn Ottosson to appearance data so that lightness, chroma and hue each behave independently.
| Colour | Result | CIELAB L* | Contrast with white |
|---|---|---|---|
| oklch(0.7 0.1 30) #d58679 | #d58679 | 63.8 | 2.79:1 |
| oklch(0.7 0.1 145) #76af77 | #76af77 | 66.4 | 2.57:1 |
| oklch(0.7 0.1 265) #809ddd | #809ddd | 64.9 | 2.70:1 |
| hsl(0 100% 50%) #ff0000 | #ff0000 | 53.2 | 4.00:1 |
| hsl(120 100% 50%) #00ff00 | #00ff00 | 87.7 | 1.37:1 |
| hsl(240 100% 50%) #0000ff | #0000ff | 32.3 | 8.59:1 |
The three OKLCH colours share a lightness of 0.7 and their contrast with white stays between 2.57:1 and 2.79:1. The three HSL colours share a lightness of 50% and their contrast with white runs from 1.37:1 to 8.59:1. Changing the hue of a button in OKLCH leaves its contrast roughly where it was. Doing the same in HSL can silently break it.
How this was calculated: OKLCH values are converted to sRGB and rounded to 8-bit HEX before the WCAG contrast ratio is taken, so the figures are for the colours a browser would show.
A theme's colours are generated by holding lightness and chroma constant and stepping the hue.
The chroma that fits in sRGB at one hue is out of gamut at another, and the browser reduces it. The set looks even only if the chroma is chosen for the most constrained hue, or each step is checked against the gamut.
A team adopts OKLCH lightness steps as a substitute for contrast testing.
Equal lightness steps give roughly, not exactly, equal WCAG contrast, and the standard is written in terms of its own luminance formula. The ramp still has to be tested pair by pair.