Two Things That are Not Great About OKLCH

I’m still a fan of the OKLCH color model and CSS function. But there are a couple of things that are confusing or weak about it, and it’s probably fair to point those out clearly.

1) Adjusting the L, C, and H values by hand is a bit dangerous

Dangerous because of totally invalid combinations. Here’s an example.

I’ve got this perfectly normal green color:

.el {
  border-color: oklch(68% 0.25 150);
}Code language: CSS (css)

Well, I know that 68% is the Lightness, 0.25 is the Chroma (sorta like saturation), and 150 is the Hue. Hue, like many of these color models, goes from 0 to 360. Increasing the Hue from the 140 where it’s at which is in Green-land should push it into Blue-land, then Purple-land, and Pink-land, then Red-land as it approaches 360.

If I just push that 150 Hue to 152… well… the color picker at OKLCH.com will tell you that that color doesn’t exist. And I guess it kind of doesn’t. Those numbers have left the P3 color space. Does that make the color “invalid”? I… don’t know. I don’t have the language for that. In the originally published draft of this post, I assumed it was invalid and would render as nothing. But, I guess you could call it good news, the specced behavior is that colors with values outside the space (and/or model?) get brought back in, so colors will never render as blank nothing. Probably smart, and good that it’s specced, but feels awfully strange to me to be picking essentially coordinates of colors that don’t exist. And then if you do that, do you still get the correct behavior of the model, like consistent lightness and all that? So much to know.

Those big empty gaps in the color space? That’s intentional! That’s part of the design of the color space. It’s like that because it actually solves some problems, like uniform brightness. But it causes others, like quite a few number combinations having this “invalid and thus must be mathed-into-place” problem. Which is usually called “clipping” I think, but I also have heard that behavior is controversial.

You can see this pretty clearly in the 3D model of the color space:

https://oklch.com/

In the sRGB color space that we’re mostly used to, well, it’s a cube, so there aren’t really “invalid” values unless you do something intentionally weird and out-of-bounds.

The programmatic champion that is HSL is within the RGB color space but is modeled like a cylinder, making it similarly difficult to make a “wrong” combination.

In rgb(), there is no “wrong” value of r, g, or b, as long as it is 0 to 255. In hsl(), there is no “wrong” value of h, s, or l, as long as it’s between 0 and 255 for the hue and 0% and 100% for the saturation and lightness. It’s no wonder why CSS adopted those models… they are just easier to reason about.

I tell you what though, color me (lol) interested in Okhsl, which seems to be a model where uniform brightness while maintaining the easy and predictable numbers of the HSL model.

2) Gradients have super awkward combinations like any other color space

I messed around with Adam’s Pen and got this.

I thought that OKLCH was supposed to be a majorly clear winner with interpolating gradients, but I’m not so sure. It’s true that it generally avoids “the gray dead zone”, but sometimes it does so by travelling through some other very unexpected color territories. More vibrant? Usually. More intuitive? Nope.

The syntax for interpolating in a particular color model is:

.el {
  background: linear-gradient(
    to right in oklch,
    yellow,
    blue
  );
}Code language: CSS (css)

So I think the answer for really nice gradients going forward is either:

  1. Pick the color model that has the best results using the syntax above, or…
  2. Use a whole bunch of color stops so the path the colors take along the way is predictable.
  3. Use OKLAB as apparently it’s the most generically best at this job.

🀘

CodePen

I work on CodePen! I'd highly suggest you have a PRO account on CodePen, as it buys you private Pens, media uploads, realtime collaboration, and more.

Get CodePen PRO

12 responses to “Two Things That are Not Great About OKLCH”

  1. For gradients, it is better to use Oklab, than OKLCH.

    Oklab is pretty good as default for gradients.

  2. Chris Lilley says:

    If I just push that 150 Hue to 152… dead. I have now left the P3 color space and the color is totally invalid and will render as nothing.

    This is completely untrue (both that it is invalid, and also that it will render “as nothing”). Can you point to some specification text that leads you to this conclusion?

  3. JD Solanki says:

    “Adjusting the L, C, and H values by hand is a bit dangerous”. Does this mean If I want to add some lightness to the color on hover state using color-mix, it’s dangerous and might give invalid or weird color?

    • Chris Coyier says:

      To me, at first, it seemed like there are lightness values that are “invalid”, but apparently that’s entirely not the case and there are clipping or correcting mechanisms in place in the spec that pull the values back in and display the closest most appropriate color. Is it possible the result is weird? I think it is, I’ve now seen some cross-browser-different clipping results, but it’s probably not a wildly huge problem.

      • Mark Buecker says:

        I find this weird. If you need a color picker to be sure not to step out of the gamut area, what’s the point of having an easy-to-read easy-to-adjust color representation like oklch? You can easily adjust the lightness of a given color, and oops you fall overboard and have to rely on dubious? correction mechanisms. I am a fan of oklch, but I think there is still room for improvement.

      • Chris Coyier says:

        I agree it’s weird, but there is an important point here not to miss (which I totally missed at first). The OKLCH.com color picker makes it very easy to pick a color “out of the gamut” and the UI will say “unavailable on any device”, but the truth is that color will actually render just fine. Browsers have an algorithm to yank it back down into renderable territory. I think how that algorithm works is subject of debate, and javascript libraries that handle color can use different algorithms, but generally they do a good job. So if you rotated the hue all the way “around” at a certain lightness, even if you’d go out of gamut at some hue values, it would probably turn out looking fine.

  4. I was currently researching going full “OKLCH” since the browser adoption is there now, but you put words on what i feel about it. It’s great for lightness and defining lightness, but …

    It’s feels like “fix one problem, get another more complex one” and if that is the case does it really solve something or add value? (…in terms of development time / cost of development)

    Fighting with lightness we’re all used to anyway but now we have to fight with being out of bounds relative to a color space and relative to whatever new technology that may or may not render “out of bounds color” in an unexpected way? Hm …

    Originally the HTML-colors where:
    color: red
    -or-
    color: #ff0000; (simple meaning: go as red as possible)

    I could expect that this simple combination would always be some sort of red. Maybe very far off from the red i wanted but it would definitely be more red then any other color. The example above would in nearly none of the case be great but it would be the maximum amount of red “possible”. (“possible” due to sRGB color space and browser color spaces …. yada yada …. )

    • I “coined the term” (I think) HCG (Hue Chroma Gray) for an (s)RGB-gamut-limited color-space (like HSL & HSV) that allows you to simply define the maximum chroma that the computer can deliver for any given hue, not the “perceived” chroma. A simple linear interpolation between the “pure hue” (RGB where one channel is maximum – 255 in 8-bit sRGB – one channel is minimum – 0 – and the third varies) and the “grayscale” (black=0% to white=100%).
      No color-space delivers it all. The OKLCh and OKLab are great, yes, but this article and this comment makes some very valid points.
      Use them ALL to figure your color, define them in your CSS specs as what you feel is best, but I am leaning to using OKLCh in the final definition.
      https://github.com/softmoonwebware/mastercolorpicker

  5. Nikil says:

    I think I figured out what is causing that weird hue shift – css is calculating gradients in oklch incorrectly by default.

    If you use any of the hue interpolation method keywords, it seems to behave correctly.

    For example

    .oklch {
    background: linear-gradient(in oklch to right longer, blue, white);
    }

    https://developer.mozilla.org/en-US/docs/Web/CSS/hue-interpolation-method
    longer, shorter, increasing, decreasing

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to Top ⬆️