OKLCH Explained: The Modern Way to Work With Color
OKLCH stands for "OK" (the OK Lab color space) plus Lightness, Chroma, Hue. It is the modern replacement for HSL when you care about perceptual accuracy - and modern CSS supports it natively in `oklch()` syntax.
In practice, OKLCH means three things: gradients look smooth without muddy middles, evenly-spaced palette colors actually look evenly spaced, and lightness numbers match what your eye reports. This article covers the why and the how.
The HSL problem in one picture
Pick five colors evenly spaced around the HSL hue wheel at 50% saturation and 50% lightness. The yellows look almost neon, the blues look gray and dim. The math is "even" but your eye reports a wildly uneven palette.
This is because HSL was designed in the 1970s as a convenient transformation of RGB, not as a model of human vision. Lightness is computed naively, ignoring that the human eye is far more sensitive to green than to blue.
What OKLCH does differently
OKLCH derives from research into how humans actually perceive color (Bjorn Ottosson, 2020). Lightness 50 means "the color looks 50% bright" regardless of hue. Hue 60 (yellow) at lightness 50 has the same perceived brightness as hue 240 (blue) at lightness 50.
Chroma replaces saturation. It is unbounded (no fixed maximum), so you can describe vivid colors that the sRGB gamut cannot represent - useful for wide-gamut P3 displays.
CSS syntax
Modern browsers (Safari 15.4+, Chrome 111+, Firefox 113+) support `oklch(L C H)` and `oklch(L C H / alpha)` directly:
.brand {
color: oklch(0.65 0.18 250); /* lightness 0-1, chroma 0-0.4ish, hue 0-360 */
background: oklch(0.95 0.02 250);
}
/* Gradient that interpolates in OKLCH */
.hero {
background: linear-gradient(in oklch, oklch(0.7 0.2 30), oklch(0.7 0.2 290));
}The `in oklch` keyword on `linear-gradient` and `color-mix` tells the browser to interpolate in OKLCH space, which is what fixes the "muddy middle" problem in old gradients.
When to use OKLCH (and when not to)
Use OKLCH when: building gradients, generating palettes, mapping a brand color across lightness scales (50-950), interpolating colors at runtime with `color-mix`, designing for wide-gamut displays.
Stick with HEX/RGB when: matching an exact brand color from a brand book, working with legacy systems that do not parse `oklch()`, or talking to designers who think in HSL.
- Browser support: Safari 15.4+, Chrome 111+, Firefox 113+ (≈97% coverage as of 2025).
- Fallback: serve HEX/RGB to old browsers via `@supports not (color: oklch(0 0 0))`.
- Tooling: every modern color tool (Tailwind v4, ColorUI, Radix Colors) speaks OKLCH internally.
Try the related tools
Frequently asked questions
Is OKLCH the same as Oklab?
Oklab is the underlying perceptual color space (lightness + two opponent axes a, b). OKLCH is a polar transformation of Oklab where the a/b axes become chroma + hue, easier for designers to reason about.
What is the maximum chroma value in OKLCH?
There is no fixed maximum - chroma is unbounded in the spec. In practice, sRGB-displayable chroma maxes around 0.32 for the most vivid hues, and P3 displays can reach about 0.4.
Should I rewrite my CSS in OKLCH?
No need to retrofit working code. Use OKLCH for new tokens, gradients, and color-mix interpolations. Existing HEX/RGB values are fine.
Does Tailwind support OKLCH?
Yes - Tailwind v4 ships its default palette in OKLCH, and v3 accepts OKLCH in arbitrary values like `bg-[oklch(0.65_0.2_250)]`.