Color Spaces & Models
RGB, HSL, CIELAB, and OKLCH — what each is for and where each breaks.
A color space is a coordinate system for color: a repeatable way to turn a perception into numbers and back. Different spaces optimize for different things - driving hardware, intuitive editing, or matching human perception - and most day-to-day color frustration comes from using a space outside its design brief.
What is a color space?#
Because human vision is trichromatic, three numbers suffice to describe any color a display can show. A color space defines what those three axes mean and which real-world color each coordinate maps to. Two properties matter constantly in practice:
- Device-dependent vs. absolute- “100% red” in raw RGB means whatever the panel's red sub-pixel emits; an absolute space like CIE XYZ names the same perceived color on every device.
- Perceptually uniform or not - whether equal moves in coordinates produce equal-looking changes. (The next chapter is devoted to this.)
Device spaces: RGB and sRGB#
Displays mix red, green and blue light, so RGB triplets are the native language of screens. sRGB (standardized in 1996) pinned down exactly which red, green and blue - and a transfer function(“gamma”) that allocates more of the 0–255 code range to dark tones, where eyes are more sensitive. The web assumes sRGB unless told otherwise; a plain #3b82f6 is an sRGB value.
HSL: intuitive but misleading#
HSL rearranges sRGB into hue, saturation, and lightness - axes that finally sound human. The catch: HSL is a purely geometric transform of RGB, with no perceptual modelling. Its “lightness” treats fully saturated yellow and fully saturated blue as equally light (both L = 50%), while your eye sees the yellow as far brighter:
The same flaw makes HSL-generated palettes uneven: stepping L by 10% yields big visual jumps in some hues and barely visible ones in others. HSL is fine for quick, rough adjustments - just don't build a design system's lightness scale on it.
CIE spaces: XYZ and LAB#
In 1931 the CIE measured how average observers match colors and published CIE XYZ: the first absolute, device-independent space. XYZ can name every visible color, but its axes aren't perceptual. CIELAB (1976) reshaped XYZ so that distances roughly match perceived difference - introducing the L*, a*, b* axes and the ΔE color-difference metric. LAB was a huge step, but it distorts blue hues (gradients through blue bend purple) and its lightness still drifts with chroma.
OKLab (Björn Ottosson, 2020) is a numerically small fix with outsized practical impact: same shape as LAB, but fitted against better data so hue stays stable while lightness or chroma change. OKLCH is simply OKLab expressed in cylindrical coordinates - lightness, chroma, hue - which is the form designers actually want to edit.
OKLCH, coordinate by coordinate#
| Axis | Range | Meaning |
|---|---|---|
L | 0 – 1 | Perceived lightness. 0 is black, 1 is white. Unlike HSL's L, equal steps look equal across all hues. |
C | 0 – ~0.4 | Chroma: distance from gray. 0 is achromatic; the usable maximum depends on hue and lightness (and on the display's gamut). |
H | 0 – 360° | Hue angle. ~30° red, ~140° green, ~260° blue. Changing only H keeps lightness and chroma genuinely constant. |
In CSS
/* oklch(L C H [/ alpha]) - supported in all modern browsers */
.accent {
color: oklch(0.65 0.19 250); /* a mid blue */
}
.accent-hover {
color: oklch(0.58 0.19 250); /* same hue & chroma, darker */
}
.accent-subtle {
color: oklch(0.65 0.05 250 / 80%); /* desaturated, translucent */
}Notice what the code demonstrates: a hover state is one number away from its base color, and the relationship is stated in perceptual terms. The equivalent hex pair (#4a8fe0 → #3577c7) hides that intent completely.
Choosing a space#
| Task | Use | Why |
|---|---|---|
| Storing / transmitting web colors | sRGB hex or rgb() | Universal, compact, assumed default |
| Quick eyeball tweaks | HSL | Familiar axes; fine when precision doesn't matter |
| Design-system palettes & scales | OKLCH | Even steps, stable hues, CSS-native |
| Measuring color difference | OKLab / ΔE | Distances approximate perception |
| CMYK (via ICC profiles) | Matches subtractive ink mixing |