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-4] Spec isn't clear whether powerless check or carryover check is done first #8602

Closed
tabatkins opened this issue Mar 16, 2023 · 1 comment

Comments

@tabatkins
Copy link
Member

In https://w3c.github.io/csswg-drafts/css-color/#powerless we say that extreme values of some components (like a 0 chroma) make other components (like hue) "powerless" - they can't affect the result so any value is exactly equivalent. When a color with such a component is produced by color space conversion, we treat the powerless components as missing, so interpolation doesn't work with an arbitrary nonsense value for the powerless component.

In https://w3c.github.io/csswg-drafts/css-color/#interpolation-missing we define that if you're interpolating colors that need to be converted into the interpolation space, any missing components will be "carried forward" to analogous components in the result of the conversion, again so you don't interpolate with a nonsense value. A missing hue from hsl() becomes a missing hue for oklch(), etc.

What we don't define is the relative ordering of these two operations when they both apply.

In #8563 (comment) gives an example where an hsl(90deg 50% none) color is interpolated in oklch space with another color. The two possible orders produce very different results.

  • If the powerless check comes first, then we first convert the hsl color, getting oklch(0 0 0). That has a zero lightness, rendering both chroma and hue powerless, resulting in oklch(0 none none). Then we carry forward the missing lightness from the original color, getting oklch(none none none).
  • If the carry-forward comes first, we again first get oklch(0 0 0). Then we carry forward the missing lightness, giving oklch(none 0 0). Then we check for powerlessness - a zero chroma renders the hue powerless, giving oklch(none 0 none).

Both results end up just taking the lightness and hue from the opposing color, but they differ on whether they interpolate the chroma or just take it.

I think the second option (carry-forward is done first) makes the most sense. We got black because we filled in the missing lightness with 0 (since we need some number to do the conversion); immediately paying attention to that fake zero lightness doesn't seem correct.


I was hoping we could define an even friendlier option that "carries forward" non-missing components too, if the missing component's "default value" we used for conversion renders other components powerless. (After all, the 0 chroma we got in the result above is just as fake as the 0 lightness, since it came about due to the fake 0 lightness.) But unfortunately "analogous component" doesn't mean "easily convertable" component; you can't just carry forward a 90deg hsl hue into an oklch hue, or similarly for chroma.

So this just confirms that manually using none is a tool for authoring convenience and requires control over all parts of the transition; we can't actually do smart things with it when conversions start happening.

@svgeesus
Copy link
Contributor

What we don't define is the relative ordering of these two operations when they both apply.

Right, we don't and should.

I think the second option (carry-forward is done first) makes the most sense.

I agree.

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

No branches or pull requests

2 participants