The problem OKLCH solves
HSL promised intuitive color manipulation. Change the lightness, keep the hue and saturation. Simple. Except it lied.
In HSL, a blue at 50% lightness and a yellow at 50% lightness look completely different in perceived brightness. Yellow appears vastly brighter to the human eye, even though the math says they're the same. This is because HSL models the color space of a display, not the color perception of a human. It's a hardware model pretending to be a perceptual one.
/* HSL: "same lightness" but wildly different perceived brightness */
--blue: hsl(230 100% 50%); /* looks dark */
--yellow: hsl(60 100% 50%); /* looks bright */
--green: hsl(120 100% 50%); /* looks medium-bright */OKLCH is perceptually uniform. When you set two colors to the same lightness in OKLCH, they actually look the same brightness to your eyes. This is not a subtle difference. It fundamentally changes how you build color scales and palettes.
/* OKLCH: same lightness = same perceived brightness */
--blue: oklch(0.60 0.20 260); /* looks medium */
--yellow: oklch(0.60 0.15 90); /* looks medium */
--green: oklch(0.60 0.18 145); /* looks medium */Understanding OKLCH values
OKLCH has three channels, just like HSL. But they map to different concepts:
L (Lightness): 0 to 1. How bright the color appears. 0 is black, 1 is white. Unlike HSL, this is perceptually accurate.
C (Chroma): 0 to ~0.4. How vivid the color is. 0 is completely neutral gray. Higher values are more saturated. The maximum depends on the hue. Greens can reach higher chroma than blues.
H (Hue): 0 to 360. The color itself. Similar to HSL hue but rotated slightly. Red is around 25, orange around 60, yellow around 90, green around 145, cyan around 195, blue around 260, purple around 300, pink around 350.
/* Anatomy of an OKLCH color */
oklch(0.65 0.20 260)
^^^^ ^^^^ ^^^
| | └── Hue: blue
| └──────── Chroma: vivid
└────────────── Lightness: mediumBuilding color scales in OKLCH
The killer advantage: building a 50-950 color scale is straightforward. Keep the hue constant, taper the chroma at the extremes, and step the lightness evenly.
@theme {
/* Indigo scale: even lightness steps, tapered chroma */
--color-indigo-50: oklch(0.97 0.01 277);
--color-indigo-100: oklch(0.93 0.03 277);
--color-indigo-200: oklch(0.87 0.07 277);
--color-indigo-300: oklch(0.78 0.12 277);
--color-indigo-400: oklch(0.68 0.17 277);
--color-indigo-500: oklch(0.59 0.21 277);
--color-indigo-600: oklch(0.50 0.19 277);
--color-indigo-700: oklch(0.43 0.16 277);
--color-indigo-800: oklch(0.36 0.13 277);
--color-indigo-900: oklch(0.27 0.09 277);
--color-indigo-950: oklch(0.20 0.06 277);
}Every step looks evenly spaced to the human eye. The chroma peaks around 400-500 (where colors are most vivid) and tapers toward the light and dark ends (where colors approach white and black). This is exactly how Tailwind v4's built-in palette is constructed.
What P3 color space unlocks
Every hex color and HSL value you've ever written is in sRGB color space. sRGB was defined in 1996 for CRT monitors. Modern displays (every Apple device since 2016, most Android flagships, high-end monitors) support Display P3, which covers about 25% more colors than sRGB.
If you suspected your hex colors looked duller than they should on a modern screen, you were right. sRGB literally cannot represent the most vivid reds, greens, and oranges that your display can show.
/* sRGB: the brightest red you can get */
--red-srgb: #FF0000;
/* P3: a more vivid red your display can actually show */
--red-p3: oklch(0.63 0.29 29);
/* The P3 red is visibly more vibrant on supported displays */OKLCH can represent P3 colors natively. When you write oklch(0.63 0.29 29), the browser renders it in P3 on supported displays and gracefully falls back to the closest sRGB equivalent on older screens. No feature detection. No media queries. It just works.
Using P3 colors in Tailwind v4
Tailwind v4's default palette already uses OKLCH values that stay within sRGB gamut for maximum compatibility. But you can push into P3 for accent colors where vibrancy matters:
@theme {
/* Standard sRGB-safe brand color */
--color-brand: oklch(0.59 0.21 277);
/* P3-enhanced accent for CTAs and highlights */
--color-accent-vivid: oklch(0.65 0.30 145);
/* P3 red for urgent/destructive states */
--color-destructive-vivid: oklch(0.58 0.28 29);
}The high chroma values (0.28-0.30) push these colors into P3 territory. On a MacBook or iPhone, they'll pop with vibrancy that hex colors can't match. On an older monitor, they gracefully degrade to the closest available color.
Gradients are dramatically better
The most visible improvement is in gradients. sRGB gradient interpolation produces muddy midpoints, especially between complementary colors. A gradient from blue to yellow goes through a grayish-green in sRGB. In OKLCH, the interpolation follows the perceptual color space, producing clean, vibrant transitions.
/* Tailwind v4 gradient: interpolated in OKLCH by default */
<div className="bg-gradient-to-r from-blue-500 to-yellow-500">
/* Clean transition, no muddy midpoint */
</div>
/* Custom OKLCH gradient in CSS */
background: linear-gradient(
in oklch,
oklch(0.59 0.21 260),
oklch(0.80 0.18 90)
);Practical impact on your theme
You don't have to convert your entire theme to OKLCH today. Hex and HSL still work in Tailwind v4. But understanding OKLCH gives you three practical advantages:
1. Better color scales. When you build a 50-950 ramp in OKLCH, the steps are perceptually even. No more manually tweaking each shade because blue-400 looks too dark next to green-400.
2. Consistent contrast. When two colors share the same L value in OKLCH, they have the same contrast ratio against any background. This makes accessibility calculations predictable.
3. Vibrant accents. P3 colors through OKLCH give you access to more vivid reds, greens, and oranges that sRGB simply cannot display. Use them sparingly for maximum impact.
OKLCH is not a trend. It's the correction CSS has needed since HSL was introduced. Tailwind v4 adopting it as the default means the entire ecosystem moves toward perceptually accurate color. For the full v4 color migration story, read Tailwind v4 Color System. For how CSS variables fit into the picture, see CSS Variables Color System. And for dark mode considerations with these new color capabilities, check Dark Mode Color System. SeedFlip exports design seeds in formats that work across sRGB and OKLCH. 104 curated color systems, ready for both Tailwind v3 and v4.