Comparison
OKLCH vs HSL
Both are cylindrical: a hue angle, a colourfulness axis and a lightness axis. Only one of them measures lightness in a way your eye agrees with.
Short answer. Use OKLCH for anything you generate — ramps, hover states, accessible pairs, gradients — because equal steps in it look equal; keep HSL only for reading palettes that are already written in it.
The difference is not stylistic. HSL's L is the midpoint between the largest and smallest RGB channel — a cheap arithmetic result with almost no relationship to perceived brightness. hsl(60 100% 50%) is a blazing yellow and hsl(240 100% 50%) is a dark blue, and HSL insists both are 50% light. OKLCH's L is a perceptual scale fitted to how people actually report lightness, so two colors sharing an L look equally bright regardless of hue.
That single property is what makes generated color work. A ramp built by stepping HSL lightness bunches up at the dark end and lands differently for every hue, which is why a design system numbered on HSL steps has a 600 that means one thing for blue and something else for yellow. The same ramp in OKLCH is even across the board.
The second real difference is chroma. HSL reports saturation as a percentage of an unstated maximum, which hides the fact that the maximum varies enormously with hue and lightness — sRGB simply holds more vivid yellow than vivid blue. OKLCH reports chroma as an absolute distance from gray, so asking for more than the gamut has is visible as a number rather than a silent clip.
OKLCH vs HSL, side by side
| Dimension | OKLCH | HSL |
|---|---|---|
| Lightness axis | Perceptual — equal steps look equal | Arithmetic — a 50% blue looks far darker than a 50% yellow |
| Colourfulness axis | Absolute chroma, roughly 0–0.37 in sRGB | Saturation as a percentage of an unstated maximum |
| Hue uniformity | Even; equal angles are equally different | Uneven; large perceptual jumps in some sectors |
| Gamut behaviour | Out-of-gamut requests are visible in the number | Silently clipped, often shifting hue |
| Generating ramps | Reliable across every hue | Bunches at the dark end, inconsistent per hue |
| Interpolation | Clean; no muddy midpoint | Passes through desaturated grey |
| CSS support | All current browsers | Universal, including very old browsers |
| Readability by hand | Chroma takes some learning | Immediately intuitive |
Where this comparison is unfair
HSL is not useless. It is universally supported, it is what a great deal of existing CSS is written in, and for a one-off tweak to a colour you already have — nudge the lightness, drop the saturation — it is faster to reason about than looking up a chroma value.
OKLCH also has a genuine learning cost. Absolute chroma has no intuitive ceiling until you have used it a while, and the maximum moves as you change lightness or hue. That is the space being honest about the gamut rather than a flaw, but it does mean the first hour is slower.
Frequently asked questions
Is OKLCH better than HSL?
For generating color, yes, decisively — its lightness is perceptual so equal steps look equal, which HSL cannot offer. For hand-editing an existing value in a codebase already written in HSL, the advantage largely disappears.
Can I use OKLCH in CSS today?
Yes. oklch() is supported in every current browser. If you need to cover older ones, ship a hex fallback first and let the oklch() declaration override it, or gate on @supports (color: oklch(0% 0 0)).
Why does HSL lightness not match what I see?
Because it is defined as (max + min) / 2 over the gamma-encoded RGB channels, which is a computation about the numbers rather than about light. Perceived brightness is dominated by the green channel — green counts for roughly 72% of luminance and blue for 7% — and HSL weights all three equally.
What is chroma in OKLCH?
The distance from the neutral grey axis at that lightness — an absolute quantity, not a percentage. Zero is grey; the maximum sRGB can reach is around 0.37, and how much is available at any point depends on both the lightness and the hue you asked for.
Try it yourself
Definitions
- OKLCHOKLCH is the cylindrical form of OKLab: perceptual lightness, chroma as an absolute distance from gray, and hue as an angle in degrees.
- HSLHSL is sRGB rewritten in polar form as hue, saturation and lightness — convenient to type and perceptually inaccurate.
- ChromaChroma is how far a color sits from gray at its own lightness — an absolute measure of colorfulness, not a percentage of some maximum.
- LightnessLightness is how bright a color appears to a human observer, as distinct from how much light it physically emits.
- GamutA gamut is the set of colors a given device or color space can actually produce.
Further reading
Other comparisons
- WCAG contrast vs APCAOne is the standard you will be measured against. The other is the better model of what your eye is doing. You need both, for different reasons.
- Lab vs OKLabSame shape: a lightness axis and two opponent axes. Forty-four years apart, and fitted to different data.
- HEX vs RGBThis is not a question about color. Both are sRGB, both carry exactly the same information, and every hex code has an identical rgb() form.
- RGB vs CMYKOne model adds light, the other removes it. That is not a detail — it changes which colors are reachable and which conversions can be trusted.
- sRGB vs Display P3P3 covers around 25% more area than sRGB. Almost all of it is in the reds, oranges and greens; there is very little extra blue.