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

DimensionOKLCHHSL
Lightness axisPerceptual — equal steps look equalArithmetic — a 50% blue looks far darker than a 50% yellow
Colourfulness axisAbsolute chroma, roughly 0–0.37 in sRGBSaturation as a percentage of an unstated maximum
Hue uniformityEven; equal angles are equally differentUneven; large perceptual jumps in some sectors
Gamut behaviourOut-of-gamut requests are visible in the numberSilently clipped, often shifting hue
Generating rampsReliable across every hueBunches at the dark end, inconsistent per hue
InterpolationClean; no muddy midpointPasses through desaturated grey
CSS supportAll current browsersUniversal, including very old browsers
Readability by handChroma takes some learningImmediately 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

Further reading

Other comparisons