Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-color][css-images] Interpolation method / color space that favors chroma over lightness #10135

Open
romainmenke opened this issue Mar 25, 2024 · 5 comments

Comments

@romainmenke
Copy link
Member

romainmenke commented Mar 25, 2024

Current implementations clip out of gamut colors, which happens to produce darker but more vibrant colors in some cases.

This can easily be seen as a feature instead of a bug.

The current specifications are all clear that clipping should not be applied and that gamut mapping by reducing chroma in oklch is the intended method to make colors displayable. So this is not a spec issue.

That it is easily doable with clipping does mean that authors are playing around with and are finding a use for the incorrect behavior.


Is there a broad use case for interpolating in such a way that colors are as vibrant as possible between colors?

Is this useful for darker and/or less vibrant gradients?

I know that @argyleink has played around with this a lot, maybe he can share some more insights?

Authors can manually define extra color stops to have the desired effect, but that isn't trivial.


Has there been any research into this?

The properties that seem to be favored:

  • oklch has a good distribution of hue's, while hsl is a mess.
  • hsl goes all over the place from very dark (blue) to very bright (yellow). It must preserve lightness better than hsl.
  • perceived vibrance should be the same throughout the gradient.

Some quick examples that illustrate how interpolating in oklch with out of gamut colors which are then clipped can produce visually nice results.

https://codepen.io/romainmenke/pen/ExJXoVW?editors=1100

Screenshot 2024-03-25 at 19 16 27
@argyleink
Copy link
Contributor

This can easily be seen as a feature instead of a bug

totally. if you're entering into this new color territory hearing there's more vibrant colors and you want to emulate vibrant gradient desktop backgrounds, then clipping delivers, and does so minimally.

Is there a broad use case for interpolating in such a way that colors are as vibrant as possible between colors?

gradients? like you're showing and noticing here. in nearly every instance i want to make them. i havent seen a single gradient i prefer mapping vs clipping. it's almost as if clipping is more desirable in all cases except when you're trying to use it for vibrant AND accessible calculated combinations. in those cases, preserving the lightness helps with the 2nd part of that intent, the accessible part. the solution tho is pretty simple, drop chroma in the math. i'm currently careful with my chroma usage when building dynamic palettes but liberal with it when making gradients. sometimes pushing the chroma far out can yield some really juicy and smooth gradients.

Has there been any research into this?

HCT seeks to strike a balance here, with a reliable lightness lever while also enabling vibrant gradients and nice interpolation.

observations

  1. the vibrant result is easy to achieve without special knowledge about underlying implementation behaviors
  2. will continue to stay vibrant across various screen capabilities over time
  3. vibrance without knowing anything about the device gamut or adding additional color stops, like a very naive request for a powerful color results in a powerful color
  4. gradients with mapping often look like a narrow gamut gradient next to a a clipped gradient which looks wide gamut, so convincing a designer for example, is hard since their eye is naturally drawn to the juicier gradient

@facelessuser
Copy link

facelessuser commented Mar 25, 2024

HCT seeks to strike a balance here, with a reliable lightness lever while also enabling vibrant gradients and nice interpolation.

Just to clarify, HCT doesn't do anything magical. They are using the same lightness preserving, chroma reduction GMA. They actually do a tighter chroma reduction than the currently suggested CSS algorithm. I've been able to replicate their behavior here. That is how they produce their tonal palettes. I am unaware of them doing anything else. They use CAM16 for perceptual hues and Lab D65 lightness in their model to provide good contrast.

To be honest, HCT is based on CAM16 which isn't the best preserver of hue. CAM16 still has the purple hue shift. You can actually produce tonal palettes in OkLCh simply by using Lab (D65 white point) to scale your lightness properly. And you'll avoid the purple shift in blue.

Example.

Screenshot 2024-03-25 at 4 09 47 PM

@argyleink
Copy link
Contributor

They are using the same lightness preserving, chroma reduction GMA.

oh! good to know, ty! i'll dig into this and see what I can find.

CAM16 still has the purple hue shift

I had noticed the hue shift occasionally yeah, def worth calling out.

fwiw, i dont think HCT is the solution, but I thought I'd seen reliable gradient vibrance and palette output, but maybe it's just the examples and I havent gotten my hands dirty enough with it.

@facelessuser
Copy link

@argyleink I believe their Material Color Utilities, when using their blend function, blends in CAM16 UCS and then copies the original chroma and lightness over. So it isn't a straightforward interpolation like CSS does: https://github.com/material-foundation/material-color-utilities/blob/main/typescript/blend/blend.ts#L59.

@facelessuser
Copy link

facelessuser commented Mar 26, 2024

@argyleink

So, I've implemented Google's HCT blend as an example, and then did something similar to OkLCh. The results aren't exactly like Google's because they lose precision because they keep converting back to 8bit hex, but the idea is exactly the same. Again, not so magical once you know what is happening.

Example.

Screenshot 2024-03-25 at 6 18 49 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants