Skip to content
ChromaBrew
Color scales

OKLCH explained for frontend developers

What the L, C and H channels actually mean, why OKLCH is perceptually uniform, and where to use oklch() in real CSS — scales, mixing and shade generation.

The three channels, decoded

OKLCH is a cylindrical color space with three channels. L (lightness) runs 0 to 1 and is designed so that equal steps look like equal steps to the eye — the reason it beats HSL for anything graded. C (chroma) is how far the color sits from neutral gray, roughly 0 to 0.37 for sRGB colors. H (hue) is an angle in degrees, 0–360, the same mental model as HSL's hue.

You read an oklch() value left to right: oklch(0.68 0.24 292) is 'lightness 68%, quite saturated, in the violet azimuth'. Because the channels are perceptual rather than derived from an RGB primary, a value communicates feel, not math — that is the entire point.

Why 'perceptually uniform' actually matters

Hex and RGB channels are hardware math: stepping red from 40 to 42 is measured in electricity, not in how the color feels. HSL is closer to human language, but its lightness curve is visibly non-linear — a gradient from hsl(240 100% 10%) to hsl(240 100% 40%) looks like it stops moving halfway through. OKLCH fixes that with a lightness axis matched to human perception.

The practical consequence: a shade scale computed in OKLCH has evenly spaced steps, while the same scale computed in RGB has clumps of near-identical steps in the middle and abrupt jumps at the ends. That is exactly the difference you see between a hand-tuned brand scale and an auto-generated one.

Tip

Quick mental check to tell a perceptual space from a device space: in HSL, changing lightness and then converting back to hex usually keeps the hue recognisable; the failure shows up as uneven spacing, not wrong hues. ChromaBrew computes every scale and palette in OKLCH for this reason.

Where oklch() ships in CSS today

Every evergreen browser supports the oklch() and oklab() color functions, so you can write them directly in stylesheets. That makes OKLCH more than an authoring nicety — it is a publishable format, and Tailwind v4's default palette and shadcn/ui themes are written in it.

The interesting reveal is how the two live sides of the toolchain shake out: ChromaBrew's full design-system export writes shadcn-style oklch() values into :root and .dark blocks, while its plain CSS and Tailwind exports keep literal hex per token. Both are deliberate — oklch keeps your theme readable and tweakable, hex keeps your output maximally interoperable.

:root {
  --primary: oklch(0.62 0.22 292);
  --primary-foreground: oklch(0.99 0 0);
}
.dark {
  --primary: oklch(0.68 0.19 292);
}

Generating scales in OKLCH

A 50–950 shade scale is built by walking OKLCH lightness between two anchors while keeping the hue. ChromaBrew's scale generator anchors the light end (50) at lightness 0.977 and the dark end (950) at 0.268, ramps chroma so the middle of the scale is most vivid, and clamps per-step by reducing chroma when a step would fall outside sRGB — never by bending the hue.

The hue signal survives, which is what keeps the whole scale recognisable as 'the same color'. Two tools consume this directly: the shade & tint scale generator, and the Tailwind color generator, which exports the finished 11-step scale as a @theme block.

  • Lightness anchors: 50 → 0.977, 500 → 0.684, 950 → 0.268
  • Chroma ramps up to 1.04× at 600, then decays toward the dark end
  • Primary color is pinned at its nearest step with a source badge
  • Tailwind v4 output uses --color-brand-50 … --color-brand-950 naming

Three rules for using OKLCH well

First, stop converting when you need to judge a relationship — read the L and C directly instead of the hex. Second, when you interpolate (mixing, gradients, color-mix()), do it in OKLCH so the midpoint lands where the eye expects it; mixing in RGB makes muddy mids. Third, remember chroma has a ceiling for a given hue in sRGB — the H stays, but very saturated colors clamp at the gamut boundary.

Related free tools

Want to apply this right now? Open the color palette generator and try it with your own brand color — free, no sign-up.