41 comments

[ 4.3 ms ] story [ 61.4 ms ] thread
I've not touched oklch, but I've played with oklab gradients a fair amount.

How do they (oklch & oklab) compare for different uses?

Really happy about oklch. You do have to learn the hue numbers, but once you do, everything is more intuitive.
Seems nice. But how to pronounce it?
The “Better Gradients” thing is dodgy.

OKLCH is a polar coordinate space. Hue is angle in this space. So to interpolate hue from one angle to another, to get from one side of a circle to the other, you go round the edge. This leads to extreme examples like the one shown:

  linear-gradient(in oklch, #f0f, #0f0)
You can also go round the circle the other way, which will take you via blue–aqua instead of via red–yellow:

  linear-gradient(in oklch longer hue, #f0f, #0f0)
The gradient shown (in either case) is a good example of a way that perceptual colour spaces are really bad to work in: practically the entire way round the edge of the circle, it’s outside sRGB, in fact way outside of the colours humans can perceive. Perceptual colour spaces are really bad at handling the edges of gamuts, where slightly perturbing the values take you out of gamut.

Accordingly, there are algorithms defined (yes, plural: not every application has agreed on the technique to use) to drag the colour back in-gamut, but it sacrifices the perceptual uniformity. The red in that gradient is way darker than the rest of it.

When you’re looking for better gradients, if you’re caring about perceptual uniformity (which frequently you shouldn’t, perceptual colour spaces are being massively overapplied), you should probably default to interpolating in Oklab instead, which takes a straight line from one side of the circle to the other—yes, through grey, if necessary.

  linear-gradient(in oklab, #f0f, #0f0)
And in this case, that gets you about as decent a magenta-to-lime gradient as you can hope for, not going via red and yellow, and not exhibiting the inappropriate darkening of sRGB interpolation (… though if I were hand-tuning such a gradient, I’d actually go a bit darker than Oklab does).

During its beta period, Tailwind v4 tried shifting from sRGB to Oklch for gradient interpolation; by release, they’d decided Oklab was a safer default.

>During its beta period, Tailwind v4 tried shifting from sRGB to Oklch for gradient interpolation; by release, they’d decided Oklab was a safer default.

I recently implemented both, first I started with OKLab which turned out really well, the gradients you get from it are amazing and the usual color sets (analogous etc.) produce really pleasing sets.

However I quickly ran into the main problem with it, which is that fiddling with its Lightness, Chroma and Hue dials doesn't produce human understandable results. For example sometimes changing L or C induces a color shift, or for some given values changing L only gives midrange values that doesn't go up or down all the way.

I then implemented OKLCH on top of that, which was the way I assumed everyone was doing it. Just have it act as the controller for the human layer, then convert to OKLab for creating gradients etc. The article doesn't really go into it, but having OKLCH as the frontend controller fixes the LCH sliders such that they produce values that make sense to us humans, while still having the superior OKLab setup in the back.

OKLCH: a color model based on OKLab (a perceptually uniform color space) where you control Lightness, Chroma (saturation), and Hue.

"OK" because "it does an ok job" according to its creater Björn Ottosson.

In the chromaticity diagram, is my Display-P3 screen mapping everything outside the triangle back into the triangle?
seems like a great idea, this will make working with colors so much easier
Aside from a few criticisms that others have already raised I think this is quite a nice introduction to OKLCH and how to use them in CSS.

With that out of the way, I'd like to go on a tangent here: can anyone explain the modern trend of not including publishing dates in blog articles? It stood out to me here in particular because the opening sentence said that "OKLCH is a newer color model" and the "newer" part of that sentence will get dated quicker than you think. The main site does mention a date, but limits it to "August 2025" so this seems like a conscious choice and I just don't get it.

[0] https://jakub.kr/

> It also works the other way around, where you can change the lightness value to create various color shades and there is no hue or saturation drift unlike in other color modes.

> In the example above, you can see that the OKLCH colors maintain consistent blueness across all of the shades, while in the HSL example, the lighter shades drift to purple and the darker ones muddy out towards grayish.

I see lots of automatic palette generator projects where the shades of each color are generated with OKLCH by only varying the lightness value on some chosen base color. The problem I find is if you look at popular open source palettes, the way the hand-crafted hue and saturation values vary across the shades for different hues isn't that predictable (the curve of the hue/saturation values over shades aren't straight lines or typical easing curves).

Hawking my own tool (using HSLuv with RGB for now), but you can load and compare the hue and saturation curves as they vary over shades of a color using example palettes from Tailwind 3, USWDS and IBM Carbon, plus tweak each shade to your liking:

Great post!

Also check out oklch.com, I found it useful for building an intuition. Some stumbling blocks are that hues aren’t the same as HSL hues, and max chroma is different depending on hue and lightness. This isn’t a bug, but a reflection of human eyes and computer screens; the alternative, as in HSL, is a consistent max but inconsistent meaning.

Another very cool thing about CSS’s OKLCH is it’s a formula, so you can write things like oklch(from var(--accent) calc(l + .1) c h). Do note, though, that you’ll need either some color theory or fiddling to figure out your formulas, my programmer’s intuition told me lies like “a shadow is just a lightness change, not a hue change”.

Also, OKLCH gradients aren’t objectively best, they’re consistently colorful. When used with similar hues, not like the article’s example, they can look very nice, but it’s not realistic; if your goal is how light mixes, then you actually want XYZ. More: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value....

Also, fun fact: the “ok” is actually just the word “ok”. The implication being that LCH was not OK, it had some bugs.

That gradient example is hilarious.

With RGB you order green salad you get green salad.

With OKLCH you order green salad you get beet soup.

There is a youtuber (Gneiss Name) making educational content through the medium of Minecraft. He's made one on OKLab as well: https://youtu.be/nJlZT5AE9zY
These IP addresses being released at some point, and making their way into something else is probably the reason I never got to fully run my mailserver from my basement. These companies are just massively giving IP addresses a bad reputation, messing them up for any other use and then abandoning them. I wonder what this would look like when plotted: AI (and other toxic crawling) companies slowly consuming the IPv4 address space? Ideally we'd forced them into some corner of the IPv6 space I guess. I mean robots.txt seems not to be of any help here.
On the comparison between Color spaces, it's weird, my monitor from 2008 does show a difference between the Display-P3 and the sRGB purple colors, yet I didn't think it'd have such a big color range. Is there some color conversion at the browser or OS-level? (my distro/desktop enables colormgr by default).
I was wondering about this exact subject the other day when working on some web dev task. Now I know why this way is better.
Thanks for this post. Hackernews is sometimes awesome for learning opportunities like this. Never heard of the model, thankful for the article.
My mind immediately translated OKLCH into "Oklachroma".
I tried working with it but had to give it up for practical purposes. Whereas the focus with HSL is on the Lightness part and the Saturation is made to fit, OKHCL does it differently. It pushes the Chroma part to it's technical limits and abuses the Hue to make it fit, but we just do not understand Chroma intuitively. I am waiting for OKHSL where the adjustments will bu much smaller and do not lead to absurd changes in intent. I already had a discussion about it somewhere else (https://www.reddit.com/r/css/comments/1jv5f0r/hue_is_an_issu...)
Quote:

    colors are much more accurate in terms of 
    how humans perceive them and it makes 
    working with them much easier
This is an aim, which I am not sure fully addressed. Think of the reason why can't I get oklch or any other method of color definition in HTML to produce the "gold color" as we humans think of it.

The fundamental reason you can't get a truly convincing "gold" color using a single value in oklch, rgb, or any other color definition is because gold is a material, not a color.

What our brain perceives as "gold" is not a single, flat hue. It's a complex interplay of light, reflection, and texture.

Point is, even with sophisticated CSS involved with linear gradient it is still a challenge

See demo at https://jsfiddle.net/oyw9fjda/

---

    <style>
    .flat-gold {
      width: 200px;
      height: 200px;
      /* Using Oklch for a perceptually uniform yellow */
      background: oklch(85% 0.11 85);
    }

    .gradient-gold {
      width: 200px;
      height: 200px;
      background: linear-gradient(
        135deg,
        oklch(60% 0.1 65),   /* Dark, desaturated shadow (brownish) */
        oklch(85% 0.11 85) 45%, /* Rich mid-tone gold */
        oklch(98% 0.1 90) 50%, /* Sharp, bright highlight (almost white-yellow) */
        oklch(85% 0.11 85) 55%, /* Back to the mid-tone */
        oklch(70% 0.1 75)       /* Softer shadow on the other side */
      );
    }

    .conic-gold {
      width: 200px;
      height: 200px;
      border-radius: 50%; /* Often looks best on a circle */
      background: conic-gradient(
        from 90deg,
        #B38728, /* Darker Start */
        #FEE9A0, /* Bright Highlight */
        #D4AF37, /* Mid-tone */
        #FEE9A0, /* Another Highlight */
        #B38728  /* Darker End */
      );
    }

    .premium-gold {
      width: 200px;
      height: 200px;
      background-color: #B38728; /* Fallback color */
      background-image:
        /* Layer 1: Sharp highlight on top */
        linear-gradient(
          175deg,
          rgba(255, 253, 240, 0.6) 0%,
          rgba(255, 215, 0, 0.2) 40%,
          rgba(136, 96, 0, 0.5) 90%
        ),
        /* Layer 2: Base metallic gradient */
        linear-gradient(
          105deg,
          transparent 35%,
          #FEE9A0 48%,
          #D4AF37 52%,
          transparent 65%
        );
      border: 2px solid oklch(60% 0.1 65);
      box-shadow: inset 0 0 10px rgba(0,0,0,0.4);
    }
    </style>

    <div class="flat-gold"></div>
    <hr />
    <div class="gradient-gold"></div>
    <hr />
    <div class="conic-gold"></div>
    <hr />
    <div class="premium-gold"></div>
> In the example above, you can see that the OKLCH colors maintain consistent blueness across all of the shades, while in the HSL example, the lighter shades drift to purple and the darker ones muddy out towards grayish.

There is a very clear shift towards green in the OKLCH lightness value change example, enormously more so than any purple vibe in the HSL example.

Clearly being able to select colours of the same perceptual intensity has value, but some of the claims here as to the benefits are exaggerated.

Does anyone know how this is different to the Munsell color space, which is also perceptually uniform?

Edit: I would imagine that the only way to definine a perceptually uniform color space is by tons of user testing. This is how Munsell developed his color space… specifically presenting test subjects with pairs of identical and near-identical color swatches and asking if they could tell the difference.

In this way, pairwise comparisom of similararity became the bedrock of color perception science.