Convert a screen sRGB color into Oklch — the cylindrical form of the modern Oklab color space, expressed as Lightness, Chroma, and Hue. Oklch is the perceptual model recommended by CSS Color 4 because it keeps hue and lightness behaving predictably, especially across blues.
How it works
Oklab is defined by Bjorn Ottosson with two fixed matrices and a cube-root nonlinearity. RGB is converted to Oklab, then to Oklch:
- Gamma-expand sRGB to linear RGB (the standard sRGB transfer function).
- Linear RGB to LMS cone responses with the first Oklab matrix, then take the cube root of each LMS value.
- LMS’ to Oklab with the second matrix, giving
L,a,b. - Oklab to Oklch:
L = L
C = sqrt(a^2 + b^2)
H = atan2(b, a) in degrees, normalised to 0-360
Example
Convert rgb(59, 130, 246):
- Oklab ≈ L 0.62, a −0.04, b −0.18
- C = √(0.04² + 0.18²) ≈ 0.19
- H ≈ 258° (blue)
- Result:
oklch(0.62 0.19 258)
Why Oklch was created: fixing LCH’s hue-shift problem
CIELAB and its cylindrical form LCH have been the perceptual color standard for print and colour science for decades. They work well in most of the colour gamut, but they have a known weakness in the blue region: as you adjust the lightness or chroma of a blue CIELAB color, the perceived hue shifts noticeably toward purple or cyan in a way that the numbers do not predict. This is called hue non-constancy.
Oklab was designed specifically to address this. Bjorn Ottosson derived the Oklab matrices
by fitting to a large perceptual uniformity dataset, optimizing for hue constancy across
lightness changes. The result is a space where the same step in the a and b dimensions
corresponds to more consistent perceived differences across the gamut, and where blues in
particular stay much more stable as lightness and chroma change.
The practical effect: when you build a tonal scale in Oklch (holding H and C constant while stepping L), the resulting palette looks visually smoother and the blues do not drift purple the way they do in CIELAB-based LCH.
Oklch vs LCH: when to use which
Both are perceptual spaces that are far more useful for palette design than HSL. The choice between them depends on your tooling and use case:
| Factor | LCH (CIELAB-based) | Oklch (Oklab-based) |
|---|---|---|
| Hue consistency in blues | Moderate — known hue shift | Better — optimized for this |
| CSS support | Native lch() in Color Level 4 | Native oklch() in Color Level 4 |
| Design tool support | Wide (Figma, Sketch) | Growing rapidly |
| Print / ICC profiles | Long history, standard in print | Newer; less common in print workflows |
| Chroma range | Roughly 0–150 for sRGB gamut | Roughly 0–0.4 for sRGB gamut |
For new CSS work and UI palette generation, Oklch is generally the better choice. For work that bridges to print or ICC color profiles, LCH/CIELAB remains more established.
Using oklch() in CSS
CSS Color Level 4 supports oklch() natively in all modern browsers. The syntax is:
color: oklch(0.62 0.19 258); /* decimal lightness */
color: oklch(62% 0.19 258); /* percentage lightness (equivalent) */
color: oklch(62% 0.19 258 / 0.8); /* with alpha */
Lightness can be expressed as either a decimal (0–1) or a percentage (0–100%); the two forms are equivalent. Chroma has no fixed upper bound but is typically below 0.4 for sRGB-gamut colors. Hue is in degrees with no unit.
A particularly useful pattern in CSS custom properties:
:root {
--brand-h: 258;
--brand-c: 0.19;
}
.button { color: oklch(0.62 var(--brand-c) var(--brand-h)); }
.button:hover { color: oklch(0.50 var(--brand-c) var(--brand-h)); }
Adjusting only lightness while keeping C and H constant produces a darker version of the same perceived hue and colorfulness — something much harder to achieve reliably in RGB or HSL.
Notes
Lightness is on a 0–1 scale (CSS also accepts a percentage). Grays have chroma ≈ 0 and an undefined hue, reported as 0. The conversion uses Ottosson’s exact published matrices and runs entirely in your browser — nothing is uploaded.