Skip to content

[css-color] Clarification needed on how missing alpha components flow through relative color syntax for hsl/hwb #10254

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

Open
weinig opened this issue Apr 26, 2024 · 17 comments
Labels

Comments

@weinig
Copy link
Contributor

weinig commented Apr 26, 2024

In the WPT test, css/css-color/parsing/color-computed-relative-color.html, there are a few examples I don't quite understand and can't figure out which language in the spec dictate them.

One is:

fuzzy_test_computed_color(`hsl(from rebeccapurple none none none / none)`, `color(srgb 0 0 0 / none)`)

What allows the alpha value to be passed through as none?

My understand here of the operations performed is:

  1. rebeccapurple converted to hsl() [hsl(270 50% 40%)]
  2. Relative color is resolved via channel arguments to hsl(none none none / none)
  3. hsl(none none none / none) is converted to color(srgb) for serialization, resolving all missing components to 0 [color(srgb 0 0 0 / 0)] (https://drafts.csswg.org/css-color-5/#serial-relative-color)

Is the intention for that last conversion (from hsl() to color(srgb)) to carry forward analogous component missing values?

Somewhat perplexingly (and perhaps just an error in the test), the corresponding test css/css-color/parsing/color-valid-relative-color has a similar example.

fuzzy_test_valid_color(`${hslFunction}(from rebeccapurple none none none / none)`, `color(srgb 0 0 0 / 0)`);

My expectation is that they should at least expect the same result.

Similarly, what would expect for missing components in the origin.

color: hsl(from hsl(none none none / none) h s l / alpha);
color: hsl(from hsl(none none none / none) h s l);
@svgeesus
Copy link
Contributor

I think this is from 4.1. Processing Model for Relative Colors :

If the alpha value of the relative color is omitted, it defaults to that of the origin color (rather than defaulting to 100%, as it does in the absolute syntax).

Missing components are handled the same way as with CSS Color 4 § 12.2 Interpolating with Missing Components: the origin colorspace and the relative function colorspace are checked for analogous components which are then carried forward as missing.

Aha! It is implied, but not directly stated, that alpha is analogous to alpha.

@svgeesus
Copy link
Contributor

If you agree, then I can add alpha to 12.2. Interpolating with Missing Components

@svgeesus svgeesus added css-color-4 Current Work css-color-5 Color modification labels Apr 26, 2024
@svgeesus
Copy link
Contributor

Is the intention for that last conversion (from hsl() to color(srgb)) to carry forward analogous component missing values?

I'm not fully sure on that point.

@weinig
Copy link
Contributor Author

weinig commented Apr 27, 2024

I totally agree that adding something to 12.2. Interpolating with Missing Components that says alpha is analogous to alpha would be great.

To restate what is probably obvious though, the bigger issue on this one is should the conversion from HSL()/HWB() to color(srgb) done for serialization be a "normal conversion" or should it be a "conversion that carries forward analogous component missing values"?

@weinig
Copy link
Contributor Author

weinig commented Apr 27, 2024

I thought a bit more about this and I think preserving the NaN (that is, using the "carries forward analogous component missing values" conversion) for alpha is better than not.

My argument is there really isn't any value in converting it to 0 here. As much as possible, serialization tries to preserve as much information as possible, and since we can preserve this, why not. (It also seems to be what Chrome does).

One things this does is beg the question, should all conversions between color spaces carry forward analogous missing components? In what cases would it not be what you want?

@romainmenke
Copy link
Member

romainmenke commented Apr 27, 2024

Is there any part of the specification that indicates that you shouldn't always carry forward analogous missing components during conversions between color spaces?

I thought this was always required.

@weinig
Copy link
Contributor Author

weinig commented Apr 27, 2024

Is there any part of the specification that indicates that you shouldn't always carry forward analogous missing components during conversions between color spaces?

I thought this was always required.

Section 4.4 is pretty explicit.

For all other purposes, a missing component behaves as a zero value, in the appropriate unit for that component: 0, 0%, or 0deg. This includes rendering the color directly, converting it to another color space, performing computations on the color component values, etc.

https://www.w3.org/TR/css-color-4/#missing

@weinig
Copy link
Contributor Author

weinig commented Apr 27, 2024

And since interpolation calls it out as a separate step, I think the implication is that if an algorithm wants carrying forward, it needs to call it out.

@romainmenke
Copy link
Member

Ah, indeed!

The intention is to preserve missing components / none as much as possible.

So if there are algorithms where it isn't stated and where it could be preserved, then we should change that.

The serialization as color(srgb) for specific cases is problematic when trying to preserve missing components / none.

It doesn't currently state that carry forward should happen. But it also makes carry forward impossible for non-alpha components when the src and dest aren't both in srgb to begin with.

@romainmenke
Copy link
Member

If you agree, then I can add alpha to 12.2. Interpolating with Missing Components

https://codepen.io/romainmenke/pen/LYvvNrb

This would also affect interpolation but there isn't any interop for none alpha.
Chrome threats none in alpha during interpolation as the alpha of the other color. Safari and Firefox do not.

@astearns astearns moved this to Unsorted in CSSWG June 2024 meeting Jun 3, 2024
@astearns astearns moved this from Unsorted to Tuesday afternoon in CSSWG June 2024 meeting Jun 3, 2024
@astearns astearns moved this from Tuesday afternoon to Wed morning in CSSWG June 2024 meeting Jun 3, 2024
@astearns astearns moved this from Wed morning to Tuesday afternoon in CSSWG June 2024 meeting Jun 3, 2024
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-color] Clarification needed on how missing alpha components flow through relative color syntax for hsl/hwb, and agreed to the following:

  • ACTION fantasai and emilio to ask their respective teams this question
The full IRC log of that discussion <fantasai> ChrisL: Alpha is analogous to alpha needs to put in the spec
<fantasai> ChrisL: Romain Menke points out that we have no interop on none alpha
<fantasai> ChrisL: Chrome interprets it as the component of the other color per spec
<fantasai> ChrisL: Safari and Firefox don't, treat as zero, unclear to me if they consider it a bug or think the spec should change.
<fantasai> ACTION fantasai and emilio to ask their respective teams this question

@emilio
Copy link
Collaborator

emilio commented Jun 12, 2024

If you agree, then I can add alpha to 12.2. Interpolating with Missing Components

https://codepen.io/romainmenke/pen/LYvvNrb

This would also affect interpolation but there isn't any interop for none alpha. Chrome threats none in alpha during interpolation as the alpha of the other color. Safari and Firefox do not.

That looks like a bug, if you change it to:

 background-color: color-mix(
    in srgb,
    color(srgb 0.4 0.4 0 / none),
    color(srgb 0.4 0 0.4 / 0.5)
  )

Then Firefox does the right thing too. It seems we lose the none information when converting the colors for interpolation.

@emilio
Copy link
Collaborator

emilio commented Jun 12, 2024

Filed https://bugzilla.mozilla.org/show_bug.cgi?id=1901991 for this btw, Safari seems to behave like Firefox.

@emilio
Copy link
Collaborator

emilio commented Jun 12, 2024

Ok, so the issue is that we treat those colors like "legacy" syntax, which generally doesn't allow none, but the / syntax does.

Chrome's handling seems broken as well, the none is completely missing when serializing:

a.style.backgroundColor = "rgb(100 100 0 / none)";
a.style.backgroundColor // 'rgba(100, 100, 0, 0)'

So, how should those colors serialize? Should we just serialize to color(srgb ..)? That'd be preferable IMO...

@svgeesus
Copy link
Contributor

So, how should those colors serialize? Should we just serialize to color(srgb ..)? That'd be preferable IMO...

That seems like a good way forward to me

@svgeesus
Copy link
Contributor

@romainmenke

This would also affect interpolation but there isn't any interop for none alpha.
Chrome threats none in alpha during interpolation as the alpha of the other color. Safari and Firefox do not.

I spotted a spec issue that might explain this, 12.2. Interpolating with Missing Components says

If the carried forward missing component is alpha, the color must be premultiplied with this carried forward value, not with the zero value that would have resulted from color conversion.

However, the table of analogous components in that section does not list alpha (it only lists color components).

svgeesus added a commit that referenced this issue Apr 17, 2025
@svgeesus
Copy link
Contributor

So, how should those colors serialize? Should we just serialize to color(srgb ..)? That'd be preferable IMO...

Do we have consensus on that? There was a request for feedback in June 2024.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Wednesday morning
Development

No branches or pull requests

6 participants