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-5] Behavior of none in relative color syntax #10151

Open
romainmenke opened this issue Mar 27, 2024 · 28 comments
Open

[css-color-5] Behavior of none in relative color syntax #10151

romainmenke opened this issue Mar 27, 2024 · 28 comments
Assignees
Labels
css-color-5 Color modification Needs Edits

Comments

@romainmenke
Copy link
Member

see : https://drafts.csswg.org/css-color-4/#valdef-color-none

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.

There is a note still in the WPT tests for relative color about none :

https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/color-computed-relative-color.html#L336-L340

  // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
  fuzzy_test_computed_color(`lab(from lab(none none none) l a b)`, `lab(0 0 0)`);
  fuzzy_test_computed_color(`lab(from lab(none none none / none) l a b / alpha)`, `lab(0 0 0 / 0)`);
  fuzzy_test_computed_color(`lab(from lab(25 none 50) l a b)`, `lab(25 0 50)`);
  fuzzy_test_computed_color(`lab(from lab(25 20 50 / none) l a b / alpha)`, `lab(25 20 50 / 0)`);

As I understand it there are two possible cases:

  • none was used in the origin color (e.g. hsl(from hsl(none 50% 50%) h s l))
  • none was used in the relative color (e.g. hsl(from green none s l))

When none was used in the origin color then it should be treated as 0 because channel keywords have type number.

When none was used in the relative color then it should behave exactly the same as it does in absolute colors.

Is this correct?

@LeaVerou
Copy link
Member

LeaVerou commented Apr 12, 2024

Both nones should be preserved. The intent is that none is only converted to 0 when you absolutely need to get a value out of it — this is not one of these cases. For example hsl(from hsl(none 50% 50%) calc(h + 20) s l) is an example where you convert to 0, and even for that I’m not sure it was a good idea. In retrospect, it should probably stay none or preserve the whole calculation (as calc(none + 20)).
none is an incredibly useful component value that extends far beyond what we originally invented it for. We need to preserve it whenever possible.

@romainmenke
Copy link
Member Author

romainmenke commented Apr 12, 2024

I am unsure if preserving as calc(none + 20) is useful or even possible. But I might be wrong here :)


If we want to preserve none as much as possible then I think these cases are of interest:

No calculation, only a channel keyword:
hsl(from hsl(none 50% 50%) h s l)

Calculation:
hsl(from hsl(none 50% 50%) calc(h + 30) s l)

Calculation where none already has meaning:
hsl(from hsl(130deg 50% none) h clamp(10, s, l) l)

Explicit none in a calculation:
hsl(calc(none + 30) 50% 50%)

Explicit none in a calculation outside of colors:
calc(none + 30)

None of these make a lot of sense when written hard coded like this, but imagine a lot of indirection with custom properties.

One option could be to preserve none when there isn't any calculation.
Only when channel keywords are used in a math expression are they cast to numbers.

Then hsl(from hsl(none 50% 50%) h s l) would be equivalent to hsl(none 50% 50%).
All other examples would treat none as 0.

@svgeesus svgeesus added the css-color-5 Color modification label Apr 12, 2024
@svgeesus svgeesus self-assigned this Apr 12, 2024
@svgeesus
Copy link
Contributor

svgeesus commented Apr 12, 2024

Is this correct?

No, but it does require a very close reading of the entire RCS section, including a snippet of text buried between two large examples, to see this.

In contrast to color-mix(), which says explicitly right at the start of 3.2

As described in CSS Color 4 §  12. Color Interpolation, both colors are converted to the specified interpolation <color-space>, taking into account any analogous components.

RCS mentions this only in passing, near the end of section 4

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.

This needs to be much more visible, and mentioned up at the front of the section.

In conclusion the spec already says what to do, but it is easy to not notice that it does so.

@svgeesus
Copy link
Contributor

The various scattered normative text snippets have been collected together and thsyntactic changes have been separated from the conceptual processing model:

This also helps with

@romainmenke
Copy link
Member Author

Thank you @svgeesus,

However this question is less about none as it is (implicitly) converted to a different or the same color space. It is more about the typings of the channel keywords and how these are processed.

So the question is if these are the same or not:

hsl(from hsl(none 50% 50%) h s l)
hsl(from hsl(none 50% 50%) calc(h) s l)

The first h arguably doesn't have a math expression so h could remain none.

While the second does and therefor matches this phrase:

However, if calculations are done on missing values, none is treated as 0.

@svgeesus
Copy link
Contributor

Yes I just spotted that phrase, which I had not collected together with the others and, as you say, it contradicts the other wording. I guess there are three options on what can be done here:

  • 0
  • calc(0)
  • calc(none)

and from what @LeaVerou was saying, the third option is the most useful. Which implies that this statement should be deleted?

@romainmenke
Copy link
Member Author

romainmenke commented Apr 12, 2024

I don't agree the 3rd is the most useful, but I might be missing the utility :)
For it to be useful it needs to have an observable effect and I can only imagine this case :

color-mix(in hsl, hsl(from hsl(none 50% 50%) calc(h + 20) s l), hsl(50deg 50% 50%))

That is an interpolation between :

  • hsl(from hsl(none 50% 50%) calc(h + 20) s l)
  • hsl(50deg 50% 50%)

I think it would be a stretch if none in calc(h + 20) was preserved as calc(none + 20) and actually had an observable effect in the interpolation.

I am not even sure what such an effect might be.


I think the specification got it right and that none always becomes 0 any time it is used in a math expression.

@svgeesus
Copy link
Contributor

svgeesus commented Apr 12, 2024

Hmm that line was added here in response to

and, earlier,

Re-reading this issue, @mirisuzanne supported the proposal by @nex to have the result be none; this had earlier been proposed by @weinig . Having it be none was also supported by myself and by @LeaVerou but opposed by @tabatkins

@tabatkins argued that

doing color-space conversion on a color that already has missing components treats those components as zero, rather than specially handling them.

(which is incorrect; I suspect that understanding was not informed by (or predated) the concept of analogous components and carrying-forward).

@mirisuzanne argued that

The relative color syntax use-cases are very similar to interpolation use-cases (where we also define a way for none to be maintained across conversions).

which is persuasive (and the model I used in this refactoring), and also @weinig argued that

There is a small argument for having some way to preserve the "missing" concept into calc() so that users could match the interpolation rules the engine uses in a custom interpolation they might implement using the relative color syntax

and

if one of the components was 'none', what the user probably really wanted was to just the other component, but if they always lose that information they are out of luck.

In conclusion, if five people argue one position while one argues the contrary, then there wasn't consensus and the issue should not have been closed.

In terms of the utility, I know @LeaVerou has been working in that area for responsive color scales that cope with dark/light mode, so invite her to comment further.

@romainmenke
Copy link
Member Author

romainmenke commented Apr 12, 2024

hehe, I need to be careful that I am fully following everything here.

When you write calc(none).
Do you mean:

  1. none is passed as none to calc, not as 0
  2. calc(none) is part of the computed value of the relative color

Because passing none to calc might be useful (e.g. clamp()).
But trying to further preserve none in the final color value when it is used in a math expression seems problematic to me.

@LeaVerou
Copy link
Member

In terms of the utility, I know @LeaVerou has been working in that area for responsive color scales that cope with dark/light mode, so invite her to comment further.

I plan to write a blog post soonish, but like I said above, none is insanely useful. It enables color-mix() to do some pretty incredible things.

@LeaVerou
Copy link
Member

LeaVerou commented Apr 12, 2024

I don't agree the 3rd is the most useful, but I might be missing the utility :) For it to be useful it needs to have an observable effect and I can only imagine this case :

color-mix(in hsl, hsl(from hsl(none 50% 50%) calc(h + 20) s l), hsl(50deg 50% 50%))

That is an interpolation between :

  • hsl(from hsl(none 50% 50%) calc(h + 20) s l)
  • hsl(50deg 50% 50%)

I think it would be a stretch if none in calc(h + 20) was preserved as calc(none + 20) and actually had an observable effect in the interpolation.

I am not even sure what such an effect might be.

I think that’s pretty straightforward: none becomes the same value as the analogous component of the other color whenever it gets interpolated. The calculation would then happen on that value, and that would become the starting value for the interpolation. It basically allows you to create dynamic colors that only fully resolve when interpolated with other colors! You only specify the bits that don't change (e.g. hue) and leave the rest none. E.g. interpolating any (polar) color with oklch(calc(none - 0.4) none none) interpolates with a darker version of that color. color-mix() between the two allows you to select any tint with a single percentage. Sure, you can do all these things with pure RCS, but this decouples the parameter from the modification entirely.

I think the specification got it right and that none always becomes 0 any time it is used in a math expression.

I think preserving it in calculations would make none even more useful and as a bonus, it would address all the weirdness around things like "is calc(none) none or 0?".
It also means that there is no magic in browser interpolation, because interpolating yourself by doing math in RCS produces the same result.

The intent behind the thing about converting it to 0 was that when converting between color spaces, there's no reasonable way to preserve it. With calculations there is.

The more I think about it, the more I think we should explicitly clarify that color space conversion is the only case when none is converted to 0 (and even then, we can avoid it in some cases) and drop the stuff about calculations.
So basically:

  • none gets converted to the analogous component of the other color during interpolation
  • none gets converted to 0 during color space conversion, with the exceptions of:
    • If all components in the source color (except alpha) are none, then they remain none. (oklch(none none none / 0%) is like transparent on steroids)
    • If the target color space includes analogous components then:
      • If there is an analogous component for the component that is none, then the none is preserved. (i.e. hsl(none 50% 50%) would get converted to oklch(55.23% 0.1637 none))
      • If after removing all analogous components, all components that remain are none, then they become none in the new color. E.g. lab(50 none none) would become lch(50 none none).
  • none gets converted to 0 if you need to output the color directly
  • none gets preserved in all other cases.

@svgeesus thoughts?

@romainmenke
Copy link
Member Author

romainmenke commented Apr 13, 2024

This issue is not about what happens to none during color space conversion.
That part is well defined and I think everyone is in agreement about how it is defined.

It is also not about the utility of none in general for colors.
This is equally well defined and agreed upon :)

I took a weird turn somewhere and started imagining preserving calc(none + 20) resulting in hsl(calc(none + 20) 50% 50%) as the final value.


If all components in the source color (except alpha) are none, then they remain none. (oklch(none none none / 0%) is like transparent on steroids)

I like this, but it is separate from this issue.
I will file a new issue specifically for this.


https://drafts.csswg.org/css-color-5/#relative-syntax

The channel keywords return a <number>; if they were originally specified as a <percentage> or an <angle>, that <percentage> is resolved to a <number> and the <angle> is resolved to a <number> of degrees (which is the canonical unit) in the range [0, 360].

But none is not a <number>.

https://drafts.csswg.org/css-values-4/#numbers

So even if color space conversions preserve none, this section still requires a conversion to <number>, at which point none becomes 0.

This applies to all channel keywords, regardless of the presence of math expressions.


https://drafts.csswg.org/css-color-5/#relative-syntax

However, if calculations are done on missing values, none is treated as 0.

This is specifically for usage in math expressions.


These two phrases make it so that none always becomes 0 even if we agree that it should remain none as a result of color space conversion when possible therein.


I think that the first (typing as <number>) is simply an oversight and needs an extra clause to clarify that none at this stage isn't converted to <number>.

The second however is less simple.
It requires defining what none means in math expressions.

For example it was recently added that none in clamp has a very specific meaning. This is very useful. I can also imagine stuff like round(1.2, none) having specific behavior.

This is work that should be done for the css-values spec.
Might be interesting to have specific handling of none at the various positions in math functions. Where the outcome is either specific behavior (clamp), 0, or invalid to preserve for future use.

@LeaVerou
Copy link
Member

I took a weird turn somewhere and started imagining preserving calc(none + 20) resulting in hsl(calc(none + 20) 50% 50%) as the final value.

Er, yes, that is the correct final value. Obviously, that is not useful by itself, but it becomes concrete once you interpolate.

The channel keywords return a <number>; if they were originally specified as a <percentage> or an <angle>, that <percentage> is resolved to a <number> and the <angle> is resolved to a <number> of degrees (which is the canonical unit) in the range [0, 360].

But none is not a <number>.

drafts.csswg.org/css-values-4/#numbers

So even if color space conversions preserve none, this section still requires a conversion to <number>, at which point none becomes 0.

Yeah, we need to fix this in the spec, but I would consider it editorial.

drafts.csswg.org/css-color-5/#relative-syntax

However, if calculations are done on missing values, none is treated as 0.

This is specifically for usage in math expressions.

These two phrases make it so that none always becomes 0 even if we agree that it should remain none as a result of color space conversion when possible therein.

I think that the first (typing as <number>) is simply an oversight and needs an extra clause to clarify that none at this stage isn't converted to <number>.

Yes.

The second however is less simple. It requires defining what none means in math expressions.

Yes, it can be argued that the second is not editorial, though the spirit of the prose has always been what I described above: the only reason to ever convert none to 0 is because you need to either convert the color to another color space where the dependencies between components are murky, OR you need to actually output it.

For example it was recently added that none in clamp has a very specific meaning. This is very useful. I can also imagine stuff like round(1.2, none) having specific behavior.
This is work that should be done for the css-values spec. Might be interesting to have specific handling of none at the various positions in math functions. Where the outcome is either specific behavior (clamp), 0, or invalid to preserve for future use.

Yes, this is something we need to keep in mind when defining math expressions, but we should have a rule about which type of none "wins" in these cases. For clamp() specifically, since none is just syntactic sugar, whereas none for components has a behavior that cannot be emulated in any other way, I would err on the side of favoring the component meaning of none.

@romainmenke
Copy link
Member Author

romainmenke commented Apr 14, 2024

I would err on the side of favoring the component meaning of none.

But what is that meaning in the context of math expressions?

A channel value of none is not the same as using none in a math expression.
Even when that none in a math expression originated from an origin color in relative color syntax.

I don't have any preference or objection. But I am really not seeing what calc(none + 20) is supposed to do or how authors are supposed to benefit from this.

Can you provide examples of inputs/outputs?


I took a weird turn somewhere and started imagining preserving calc(none + 20) resulting in hsl(calc(none + 20) 50% 50%) as the final value.
Er, yes, that is the correct final value. Obviously, that is not useful by itself, but it becomes concrete once you interpolate.

How?

For example :

color-mix(
  in hsl,
  hsl(from hsl(none 50% 50%) calc(h + 20) s l),
  hsl(50deg 50% 50%)
)

What is result of this?

A:

  1. calc(h + 20) is 0 + 20
  2. interpolated as (20 + 50) / 2
  3. results in hsl(35deg 50% 50%)

B:

  1. calc(h + 20) is none
  2. interpolated as (50 + 50) / 2
  3. results in hsl(50deg 50% 50%)

C:

  1. calc(h + 20) remains calc(none + 20)
  2. interpolated as ???
  3. results in ???

Also keep in mind that there should not be any practical difference between manually writing none and channel keyword values.

hsl(from hsl(none 50% 50%) calc(h + 20) s l)
hsl(calc(none + 20) s l)
--foo: calc(none + 20)
hsl(var(--foo) s l)

@mirisuzanne
Copy link
Contributor

C:

  1. calc(h + 20) remains calc(none + 20)

The value of none is replaced by the corresponding channel in the other color, so:

  1. interpolated as ((50 + 20) + 50) / 2
  2. results in hsl(60deg 50% 50%)

To me, that seems like expected behavior.

@romainmenke
Copy link
Member Author

🤔 But that isn't how these features are currently specified or implemented.

none is not a placeholder for the corresponding channel (i.e. & in nesting). none is a way to make or represent a missing channel. Missing/powerless channels are filled in with the corresponding value from the other color.

This would be a very large change and one that opens up more questions than it answers.


How does it work when channel keywords are used in different positions?

color-mix(
  in lab,
  lab(50% none none),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)

vs.

color-mix(
  in lab,
  lab(from lab(50% none none) l b a),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)

vs.

color-mix(
  in lab,
  lab(from lab(50% none none) l a b),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)

vs.

color-mix(
  in lab,
  lab(from lab(50% none none) l calc(b) calc(a)),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)
/* or? */
lab(50% 20% 10%)

@LeaVerou
Copy link
Member

LeaVerou commented Apr 14, 2024

none is not a placeholder for the corresponding channel (i.e. & in nesting). none is a way to make or represent a missing channel. Missing/powerless channels are filled in with the corresponding value from the other color.

This would be a very large change and one that opens up more questions than it answers.

I honestly have no idea what is confusing you here. Yes, none represents a missing channel, and gets a concrete value when interpolated with another color that does not have none in the same place. Until then, it stays none except when that is really not possible. The spec does have some issues around this and needs to be clarified ASAP, but that's far from "a very large change".

How does it work when channel keywords are used in different positions?

color-mix(
  in lab,
  lab(50% none none),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)

Yup.

color-mix(
  in lab,
  lab(from lab(50% none none) l b a),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)

lab(from lab(50% none none) l b a) becomes lab(50% none none) and color-mix(in lab, lab(50% none none), lab(50% 10% 20%)) is lab(50% 10% 20%) so yeah, that's the correct result.

color-mix(
  in lab,
  lab(from lab(50% none none) l a b),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)

Yup.

color-mix(
  in lab,
  lab(from lab(50% none none) l calc(b) calc(a)),
  lab(50% 10% 20%)
)

lab(50% 10% 20%)
/* or? */
lab(50% 20% 10%)

lab(50% 10% 20%) and the spec needs to clarify this. We cannot have discontinuities because something was wrapped in calc().

@LeaVerou
Copy link
Member

LeaVerou commented Apr 14, 2024

If anything is hairy, it's things like:

color-mix(
	in oklch, 
	oklch(50% none none), 
	oklch(50% calc(none + .1) calc(none + 180))
)`

I can see two interpretations:

  1. Both nones stay, and the resulting color has a chroma of calc-mix(50%, none, calc(none + .1))
  2. The first none yields to the second expression, since technically that is not none, so the resulting chroma is calc(none + .1)

I think 1 makes more sense, but we need to clarify.

@romainmenke
Copy link
Member Author

I honestly have no idea what is confusing you here.

What is confusing me is that, by my interpretation, none does not represent the analogous component. It makes a channel missing and missing channels are filled in with analogous components.

  • none causes missing components.
  • missing component are filled in with analogous components.

But this proposed change would change the specification so that none itself is replaced at every position it is used. It is taking me some time to wrap my head around this, mostly because I am also thinking about the impact on implementations.


I think 1 makes more sense, but we need to clarify.

I agree, if the concept is to preserve none when possible then it makes sense to continue along that line.


I would also like to have @tabatkins opinion on this as this has a wider impact than only css colors.

And I also think implementers would need to weigh in on this to make sure that this is even possible.

@romainmenke
Copy link
Member Author

romainmenke commented Apr 15, 2024

#10151 (comment)

color-mix(
	in lab, 
	oklch(50% none none), 
	oklch(50% calc(none + .1) calc(none + 180))
)

Not a single none would be preserved here.

This is mixing in lab so all none values and keywords would be handled as 0 as a result of converting from oklch to lab.

What happens when you convert between oklch and lch?
c has an analogous component between these two.
Would a value like calc(none + .1) be carried over?

I don't think it should. The .1 was written for oklch, not for lch which has a different value range.

@facelessuser
Copy link

[#10151 (comment)](#10151 (comment)

color-mix(
	in lab, 
	oklch(50% none none), 
	oklch(50% calc(none + .1) calc(none + 180))
)

...

I don't think it should. The .1 was written for oklch, not for lch which has a different value range.

From what I understand, carry forward applies during a forced conversion in interpolation. Since they are not converting to a space with analogous components, all channels should be forced to be evaluated before conversion. There shouldn't be any none values after conversion, right?

I've never been a huge fan of carry forward due to it feeling a bit magical as often color channels are not completely independent when converting, but preserving none in this case seems beyond magical 😕.

@facelessuser
Copy link

I guess you could rationalize that if "both" chroma and hue are none, it is just another way of saying both a and b are none. You would be saying that ab together is analogous with ch together, which it is as ch is the polar form of ab. I'm not huge fan of this, but I could see the argument.

I don't see how either calc(none + .1) or calc(none + 180) could be preserved in this scenario, they would have to be forced to become a real value. Currently, I think calc() would force these to be zero, which would force the final interpolation to yield zeros, not none for a and b. But if calc() was forced to yield none for the aforementioned cases, then I guess you could have the return Lab value have a and b both as none. Again, I'm not personally a huge fan of this, but admitting one could argue such a case.

@LeaVerou
Copy link
Member

LeaVerou commented Apr 15, 2024

That was a typo, the interpolation space should have been oklch! Fixed now.

That said, I did propose earlier that we expand the concept of carry forward to the other channels as a whole, in which case lab would have worked. But that was not the point of that comment.

I've never been a huge fan of carry forward due to it feeling a bit magical as often color channels are not completely independent when converting, but preserving none in this case seems beyond magical 😕.

It's the lesser of two evils though, the other one being converting none to 0.

@svgeesus
Copy link
Contributor

Do the edits made earlier resolve the "needs edits" or does the subsequent discussion mean that more changes are needed?

Do any wpt need to be altered in consequence?

@romainmenke
Copy link
Member Author

romainmenke commented May 30, 2024

I think the original issue is still present.

https://drafts.csswg.org/css-color-5/#relative-syntax

The channel keywords return a <number>; if they were originally specified as a or an <angle>, that <percentage> is resolved to a <number> and the <angle> is resolved to a <number> of degrees (which is the canonical unit) in the range [0, 360].

This implies that none is eagerly converted to a <number> and the only way to do that in the current specification is to change it to 0, as none is not a <number>.

I think this is just an oversight and changing the paragraph to this would be sufficient:

The channel keywords return a <number> or none; if they were originally specified as a or an <angle>, that <percentage> is resolved to a <number> and the <angle> is resolved to a <number> of degrees (which is the canonical unit) in the range [0, 360].


https://drafts.csswg.org/css-color-5/#relative-syntax

Same section, but only after all the examples :

However, if calculations are done on missing values, none is treated as 0.

Regardless of if this still reflects the current intentions of everyone here, it isn't ideal that this placed after all the examples.

Placing it after "The channel keywords return a <number>; ..." might be better?

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-color-5] Behavior of `none` in relative color syntax, and agreed to the following:

  • RESOLVED: `none` in calculations is converted to 0 when converting a color to a different color space. It is still preserved otherwise, and is still preserved when used as the whole value of a component.
The full IRC log of that discussion <fantasai> lea: We have this concept of "none", which defines a missing color component
<emilio> lea, can you use a mic?
<fantasai> lea: when you interpolate with another color, and the other color has an actual number
<fantasai> lea: then that component will take its value from the other color
<fantasai> lea: This concept started for representing achromatic colors
<fantasai> lea: but it also allows specifying parts of color and adding in by interpolation, which is useful
<fantasai> lea: we recently resolved to preserve none in calculations
<fantasai> lea: previously computed to zero, in order to avoid exposing color space math
<ChrisL> q+ to ask if the edits suggested in https://github.com//issues/10151#issuecomment-2140647146 are sufficient, or is more needed
<fantasai> lea: but implementers interpreted as "any time you do any math, compute to zero" which isn't needed
<fantasai> lea: in April we resolved to preserve "none" in calculations
<astearns> ack lea
<fserb> +1
<fantasai> ChrisL: Suggest we adopt changes proposed by Romain Menke
<fantasai> ChrisL: idk if we need more changes to close the issue
<fantasai> -> https://github.com//issues/10151#issuecomment-2140647146
<fantasai> lea: that's a problem from a different issue
<lea> https://github.com//issues/10211#issuecomment-2083735046
<fantasai> lea: right now we have concept of analogous color spaces
<fantasai> lea: can convert to a different color space, can convert none
<fantasai> lea: e.g. lch and oklch, a lightness of none will be preserved
<fantasai> lea: you make the none's zeroes, you convert to other color space, you plug the none's back to the alogous components
<fantasai> lea: but wouldn't work if you preserve calculations if different scales
<fantasai> lea: e.g. rgb and color(rgb)
<fantasai> lea: in color function range is 0-1
<fantasai> lea: in rgb the range is 0-255
<fantasai> lea: so adding 50 to rgb color is 20%, but srgb using color function is nonsensical
<fantasai> lea: I think that should be allowed
<fantasai> lea: not sure what the solution is here
<fantasai> lea: but preserving calculations when converting to differnet color space is iffy
<fantasai> lea: preserve for other operations, but maybe not converting colors
<astearns> ack ChrisL
<Zakim> ChrisL, you wanted to ask if the edits suggested in https://github.com//issues/10151#issuecomment-2140647146 are sufficient, or is more needed
<fantasai> lea: either preserve none as a whole or drop ti
<fantasai> ChrisL: I'm not sure
<fantasai> ChrisL: I think preserving none is the right thing, but I'm not sufficiently sure
<fantasai> lea: when converting color spcaes, numbers mean different thing
<fantasai> lea: having a whole component as none made sense, but calculations if converting it's ...
<fantasai> lea: anything we come up with would be way too weird
<miriam> +1 preserve none unless converting spaces
<emilio> nope
<fantasai> fserb: when crossing function boundaries where maybe stop making sense, you need to convert none
<fantasai> lea: agree, anythng else seems super weird
<fantasai> fserb: think about those boundaries and resolve at them
<lea> PROPOSED RESOLUTION: `none` in calculations is converted to 0 when converting a color to a different color space. It is still preserved otherwise, and is still preserved when used as the whole value of a component.
<lea> RESOLVED: `none` in calculations is converted to 0 when converting a color to a different color space. It is still preserved otherwise, and is still preserved when used as the whole value of a component.

@LeaVerou
Copy link
Member

I wonder if we could preserve it for analogous components that have the same reference range. E.g. there is no reason to drop it when converting a none hue from lch to oklch…

@romainmenke
Copy link
Member Author

romainmenke commented Jun 12, 2024

I can't re-read all the relevant spec sections at this time, but I think that this resolution doesn't solve the issue at hand.

It was already well specified how to handle none during color space conversions (and we have other issues to improve that still)

This issue was solely about some contradictions that slowly crept into the spec after some recent edits.

The current resolution would actually mean we preseve none even less than currently specified because it requires converting to 0 for any color space conversion and it doesn't mention carry forward.

Can we undo this resolution and re-visit my proposed edits?


Edit: upon re-reading the resolution it seems that maybe it just isn't that related to this issue? Hence my confusion.

This issue isn't about color space conversion or the behavior of none in math functions in relative colors.

I don't mind extra resolutions here but we should also fix the issue at hand. My proposed edits would resolve this issue :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-color-5 Color modification Needs Edits
Projects
Status: Wednesday morning
Development

No branches or pull requests

6 participants