Every screen you look at produces color by mixing red, green, and blue light. This is additive color mixing — adding all three at full intensity produces white. RGB is hardware-native: it maps directly to the three sub-pixels in each display pixel.
But RGB is not intuitive for humans. Asking someone to imagine "203, 47, 128" means nothing. That's why higher-level models exist.
HSL (Hue, Saturation, Lightness) and HSV (Hue, Saturation, Value) remap RGB into a cylindrical geometry that's more intuitive. Hue is the color wheel angle, saturation is intensity, and lightness/value controls brightness.
These models are great for quick color picking but terrible for perceptual accuracy. A saturation of 100% in HSL doesn't always look equally vivid across different hues.
CIELAB (L*a*b*) was designed for perceptual uniformity: ΔE = 1 should be a just-noticeable difference everywhere in the space. L* is lightness, a* is green-red, b* is blue-yellow. LCH is CIELAB in cylindrical form: Lightness, Chroma, Hue.
For developers, LCH is the best space for generating palettes, creating accessible color scales, and interpolating gradients that look smooth to the human eye.
Oklab by Björn Ottosson improves on CIELAB with better hue linearity and simpler
math. It's now supported in CSS via oklch() and oklab(). If you're
building modern web interfaces, OKLCH is the recommended color model for consistent, perceptually
uniform results.
A gamut is the range of colors a device or space can represent. sRGB covers ~35% of visible colors. Display P3 covers ~45%. Rec. 2020 covers ~75%. When you specify a color outside a device's gamut, it must be gamut-mapped — usually by reducing chroma until it fits.
Transfer functions (gamma curves) define how numerical values map to light output. sRGB uses a ~2.2 gamma curve. Getting this wrong — applying gamma twice or not at all — is the #1 source of washed-out or crushed images on the web.
color-mix(in oklch, …) in modern CSS