For over twenty-five years, web developers have relied on hexadecimal values (#ff0000) and rgb() or hsl() strings to style web pages. But as display technology advanced to wide-gamut P3 screens (like modern iPhones, MacBooks, and high-end monitors), the flaws of the legacy sRGB model became glaringly apparent.
Enter OKLCH, introduced in CSS Color Module Level 4 and supported across all modern browsers today.
The Problem With Traditional HSL
HSL (Hue, Saturation, Lightness) was designed in the 1970s as a human-friendly model of RGB. However, HSL is not perceptually uniform.
In HSL:
- Pure Yellow (hsl(60, 100%, 50%)) has a lightness of 50%.
- Pure Blue (hsl(240, 100%, 50%)) also has a lightness of 50%.
To human eyes, however, yellow appears blindingly bright, while blue appears dark and heavy. If you programmatically build a design system palette in HSL by keeping lightness constant while changing the hue, your yellow button will be unreadable with white text, while your blue button will pass contrast tests.
How OKLCH Solves This
OKLCH stands for: - L (Lightness): 0% to 100% (or 0.0 to 1.0). Perceptually uniform across all hues! - C (Chroma): The color saturation/purity (typically 0.0 to 0.4+). - H (Hue): The hue angle from 0 to 360 degrees.
Because OKLCH is based on human visual perception (modeled by Björn Ottosson in 2020), a Lightness of 0.6 in OKLCH has the exact same perceived brightness whether the hue is yellow, green, blue, or purple.
Native CSS Syntax
In modern CSS, you can use OKLCH directly:
``css
:root {
--brand-primary: oklch(0.65 0.22 250);
--brand-accent: oklch(0.65 0.22 30);
}
``
Because both colors share the exact same lightness (0.65) and chroma (0.22), swapping them in buttons, borders, or navigation bars maintains identical contrast against white or dark backgrounds.
