Color models
HSL vs LCH
Both describe a color by its hue — but they sit on completely different foundations. The short version: HSL is easy but lies about brightness; LCH (and its successor OKLCH) tells the truth. If you've ever wondered why a row of HSL colors at the same "lightness" looks wildly uneven, this is why — and what to use instead.
At a glance
| HSL | LCH (& OKLCH) | |
|---|---|---|
| Full name | Hue · Saturation · Lightness | Lightness · Chroma · Hue |
| Based on | sRGB (a cylindrical transform of it) | CIELAB — the CIE 1976 perceptual space |
| Perceptually uniform | No — equal numbers ≠ equal change | Yes — equal lightness looks equally bright |
| Gamut | sRGB only | Wide-gamut (Display P3, Rec.2020, beyond) |
| What 'lightness' means | Geometric, not perceptual | Perceived brightness |
| CSS function | hsl() — universal support | lch() / oklch() — CSS Color 4, modern browsers |
| Best for | Quick tweaks, legacy support | Accessible palettes, even gradients, wide gamut |
What HSL is
HSL — Hue, Saturation, Lightness — is the color model
most designers meet first, because it's intuitive and built into CSS
(hsl(210 100% 50%)). Under the hood it's just a different
way of slicing the same sRGB space your screen already uses:
spin the hue around a wheel, push saturation in or out, slide lightness
up or down. That familiarity is its strength — and the source of its one
big flaw.
Because HSL is a purely geometric transform of sRGB, its numbers don't match how your eye actually works. HSL yellow at 50% lightness looks almost luminous; HSL blue at the same 50% looks dark and heavy. Build a palette by holding "lightness" constant and you get a row of swatches that jump around in brightness. HSL also can't describe any color outside sRGB, so it has nothing to say about the wider gamuts modern displays can show.
What LCH is
LCH — Lightness, Chroma, Hue — is built on CIELAB, a color space the CIE designed in 1976 to be perceptually uniform: a given step in a value should look like the same-sized step to a human eye, regardless of hue. So in LCH, lightness is real perceived brightness, chroma is perceived colorfulness, and hue is hue. Hold lightness constant across a palette and the swatches actually look evenly bright.
LCH is also device-independent and wide-gamut: it can describe colors
beyond sRGB — into Display P3, Rec.2020 and further — which matters as
more screens render them. In CSS it appears as lch() and,
better, OKLCH (oklch()): a refinement built
on Björn Ottosson's OKLab that keeps the perceptual uniformity while
fixing LCH's hue shifts — most famously the blue that drifts toward
purple as it lightens. For modern work, OKLCH is usually the one to reach
for.
The real difference
HSL answers "where is this color in sRGB?"; LCH answers "how does this color look?" That's the whole story. HSL is convenient and universally supported, but its lightness and saturation are mathematical, not perceptual, so palettes built in it need eyeballing and manual correction. LCH/OKLCH bakes the perception in, so even ramps, predictable contrast, and clean gradients fall out almost for free — at the cost of needing a modern browser (with an sRGB fallback for old ones).
Which should you use?
- Quick tweak, a legacy codebase, or maximum support? HSL is fine. It works everywhere and everyone reads it.
- Designing a real palette, a lightness ramp, or accessible contrast? Use OKLCH (or LCH). Equal lightness actually looks equal, so your scale is honest.
- Targeting wide-gamut screens (P3) or smooth gradients? LCH/OKLCH only — HSL can't express those colors, and HSL gradients dip through muddy grey midpoints that OKLCH avoids.
Can you convert between them?
Yes — the math runs sRGB → CIELAB → LCH, and any modern color tool does it for you. But it isn't a clean one-to-one swap: HSL and LCH parametrize different spaces, so the "same" hue number won't land on the same color, and LCH can describe colors that simply have no HSL equivalent. Convert when you need to, but design in the model that fits the job.
Questions, answered
- What is the difference between HSL and LCH?
- HSL is a simple cylindrical transform of the sRGB color space — intuitive, but not perceptually uniform and limited to the sRGB gamut. LCH is built on the perceptually-uniform CIELAB space: equal lightness values look equally bright across hues, and it can describe wide-gamut colors HSL cannot.
- Is LCH better than HSL?
- For modern, accessible, perceptually-even palettes and wide-gamut displays, yes. HSL is still fine for quick tweaks and universal legacy support. Many designers now prefer OKLCH, a refined version of LCH.
- What is OKLCH?
- OKLCH is a refined LCH built on the OKLab color space. It keeps LCH's perceptual uniformity but fixes hue shifts (such as the blue-to-purple drift), so gradients and palette ramps stay clean. It is supported in current CSS via the oklch() function.
- Why does HSL lightness look wrong?
- HSL 'lightness' is a geometric value in sRGB, not a perceptual one. HSL yellow at 50% lightness looks far brighter than HSL blue at 50% lightness, so equal numbers don't mean equal perceived brightness. LCH lightness is perceptual, so it behaves predictably across hues.
- Can browsers display LCH colors?
- Yes. The lch() and oklch() functions are part of CSS Color 4 and work in current browsers. Provide an sRGB fallback (hex or HSL) for older browsers that don't support them.
- Can you convert HSL to LCH?
- Yes — through the color math (sRGB → CIELAB → LCH), and tools do it automatically. But it isn't a clean 1:1 mapping: they parametrize different spaces, and LCH can express colors outside HSL's sRGB range.
Library
Go deeper on color
Color models are the practical surface. These are the books on the theory, perception and history of color underneath them.
Torn between the two Wada dictionaries? Vol 1 vs Vol 2, compared plate by plate →
Book links are Amazon Associates affiliate links. Your price is unchanged; a small commission supports the archive. As an Amazon Associate we earn from qualifying purchases.