Modern CSS

OKLCH explained

OKLCH is a way of writing colors where the first number means what you think it means. Set two colors to the same lightness and they look equally light, whatever their hue. That sounds like a small thing. It is the difference between a color ramp that works and one you tune by hand for a week.

The three numbers

oklch(L C H) takes lightness, chroma and hue.

  • L, lightness. 0 to 1, usually written as a percentage. 0 is black, 1 is white, and the scale in between is built to match perception rather than geometry.
  • C, chroma. How colorful, starting at 0 for grey. Unlike HSL saturation it has no fixed maximum: the highest chroma a color can reach depends on its lightness and hue, and on what the display can show.
  • H, hue. An angle in degrees, same idea as HSL hue, though the angles do not line up between the two spaces.

Cobalt, #2563EB, is oklch(54.61% 0.2152 262.88). Every color page on this site shows its OKLCH alongside the older models.

The problem it solves, shown rather than claimed

Here are six blues at even HSL lightness steps, with the relative luminance each one actually has:

And the same six steps set in OKLCH instead:

The real test is across hues, though, because that is where HSL falls apart. Six hues at hsl(h, 100%, 50%) against six hues at oklch(70% 0.12 h):

Relative luminance of six hues held at one nominal lightness in each space. Lower spread means the ramp looks more even.
HueHSL 50% lightnessLuminanceOKLCH 70% lightnessLuminance
0°#FF00000.213#DA7D9B0.319
60°#FFFF000.928#D58B4B0.331
120°#00FF000.715#95A94E0.353
180°#00FFFF0.787#24B6A10.364
240°#0000FF0.072#4FA8E10.351
300°#FF00FF0.285#AA8DDE0.329

In HSL the brightest of those six hues is 12.9 times as luminous as the darkest, at identical lightness values. In OKLCH the same six hues spread by a factor of 1.1. That gap is the whole argument.

What this buys you in practice

Ramps that need no hand tuning. A nine step scale becomes a loop over lightness values and looks even across every hue in your system, so your yellow-500 and your blue-500 carry the same weight.

Gradients without a muddy middle. Interpolating two colors in sRGB passes through a grey dip. In OKLab the path stays colorful, which is why CSS gradient interpolation can now be told which space to use.

Predictable programmatic adjustment. Darken by 10 percent and you get something 10 percent darker, not a color that also shifted hue. This matters most for automatically generated states: hover, active, disabled.

Colors outside sRGB. OKLCH can address the wider gamuts modern displays support. A high chroma value simply reaches further than sRGB can go, which is a feature if your users have the screens and a trap if they do not, since the browser clamps it back into gamut.

An independent check on the math

Tailwind CSS 4.3.1publishes its whole palette in OKLCH. Running those values through this site's own OKLCH to sRGB conversion reproduces the hex values Tailwind itself ships, including blue-600 as #155DFC and slate-900 as #0F172B. That is a check by a third party's numbers, not a claim about our own code, and it is the reason the OKLCH values elsewhere on this site can be trusted.

When OKLCH is the wrong choice

  • Storing a color. Hex is still the interchange format. Design in OKLCH, ship hex where anything downstream might not understand it.
  • Guessing a value by hand. Nobody has intuition for what chroma 0.14 looks like yet. Convert from a color you already have rather than typing three numbers.
  • Judging contrast. OKLCH lightness is perceptual, but WCAG contrast is defined on relative luminance, not on it. Two colors with an OKLCH lightness difference that looks fine can still fail AA. Check the ratio.
  • Print. OKLCH is a display space. For a press, CMYK and a profile are still the conversation.

Using it today

Write it as color: oklch(54.61% 0.2152 262.88);. If you need to support a browser that does not understand it, declare a hex value first and let the OKLCH declaration override it where supported. That is one extra line and it degrades cleanly.

To get started from colors you already have, convert them with hex to OKLCH, then adjust the lightness column and convert back with OKLCH to hex.

Related

Last updated by FusionStudios. Every value on this page is computed by the same functions the tools use. How this is calculated.