Open emilio opened 2 years ago
I think you meant to cc me (@weinig).
I am a bit unclear on where CSS stands with regards to preserving input. For instance, I CSS Images 4 says this in its serialization section:
To serialize any function defined in this module, serialize it per its individual grammar, in the order its grammar is written in, omitting components when possible without changing the meaning, joining space-separated tokens with a single space, and following each serialized comma with a single space.
I would love for this to be more explicit in more places.
Gah, yeah, got tricked by the autocomplete, sorry!
@emilio said:
In Gecko, I opted for the approach of keeping color-mix() in the specified value, but resolve at computed-value time (except for currentColor which is special of course, but that's not observable anyways because getComputedStyle returns resolved colors).
That seems preferable to me; and currentColor gets resolved at used-value time.
@weinig I assume the fact that WebKit currently resolves color-mix()
at parse time, and the fact that it currently doesn't handle currentColor in color-mix()
, are related?
CSS Color 5 doesn't mention color-mix()
in the Resolving Color Values section, and it should. Maybe we can nail this down this week (in this issue, and resolve on the call)?
CSS Color 5 doesn't mention
color-mix()
in the Resolving Color Values section, and it should. Maybe we can nail this down this week (in this issue, and resolve on the call)?
Proposed text for review is now at
7.2. Resolving color-mix()
values
and revised text and example at
7.1 Resolving color-contrast()
values
Both of these specifically call out currentColor, which does not resolve to a corresponding color in a specific color space.
Comments and corrections welcome.
Once we have agreement I will add more examples to both sections.
The CSS Working Group just discussed css-color] Resolving color-mix() / color-contrast()
.
I implemented color-contrast()
in chromium a little while ago, but I've been holding off on shipping it because I got feedback that I was doing the whole calculation at parse time instead of used-value time, which was making it not work properly with currentColor
.
I guess I sort of assumed that color-contrast was already specced to be resolved at used-value time instead of parse time, but now that I see this issue I'm not so sure. I'm having a hard time fully following the discussion here, but is the idea that we should make color-contrast get resolved at used-value time and support currentColor? Are there any WPTs for this?
(I don't know what the difference is between used-value time and computed-value time)
cc @andruud
(I don't know what the difference is between used-value time and computed-value time)
Computed values inherit to children, so that affects currentColor
@emilio @weinig these edits look good now?
@svgeesus The specified value shouldn't resolve colors. color-mix(blue, red)
should be color-mix(blue, red)
, not color-mix(rgb(0, 0, 255), rgb(255, 0, 0))
.
Ah, I see. So, just remove the text there about specified values?
@emilio now?
I think so, thanks!
fantasai: Seems like we should fix up spec to say what we want shipped and once that's ready we say go ahead Rossen_: Do you want to go back and do that and let us know once ready
Its ready, here is the text on resolving color-mix()
and resolving color-contrast()
From https://drafts.csswg.org/css-color-5/#resolving-mix:
Otherwise (if currentColor was used in the function), the computed value is the color-mix() function with each
parameter...
Is currentColor
the only issue? What about system colors that depend on the color-scheme computed value, e.g.:
div { color: color-mix(in lch, canvastext, blue) }
div.dark { color-scheme: dark; }
Depending on whether an element has the class "dark" or not, the computed value will be different. Serializing the color declaration in the div rule above cannot give a reasonable serialization as a <color>
.
@lilles, who I am basically quoting here, might have more to say.
@svgeesus The specified value shouldn't resolve colors.
color-mix(blue, red)
should becolor-mix(blue, red)
, notcolor-mix(rgb(0, 0, 255), rgb(255, 0, 0))
.
@svgeesus Should we add some tests here to reflect that? https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/color-valid-color-mix-function.html
Should we add some tests here to reflect that?
That would be great
System colors are already defined:
Each
<system-color>
keyword computes to the corresponding color in its color space. However, such colors must not be altered by 'forced colors mode'.
System colors are already defined:
Each
<system-color>
keyword computes to the corresponding color in its color space. However, such colors must not be altered by 'forced colors mode'.
What is this in response to?
Should we add some tests here to reflect that?
That would be great
See: crrev.com/c/3945930
It seems like firefox nightly never eagerly evaluates the resulting color mix, input values are always returned as-is at specified value time. I'm beginning to think that the expectations in this test are entirely incorrect?
What is this in response to?
It was in response to
Is currentColor the only issue? What about system colors that depend on the color-scheme computed value, e.g.:
div { color: color-mix(in lch, canvastext, blue) } div.dark { color-scheme: dark; }
Depending on whether an element has the class "dark" or not, the computed value will be different. Serializing the color declaration in the div rule above cannot give a reasonable serialization as a
<color>
.
Wouldn't the serialization on the div use the initial value of color-scheme
which is normal
?
Okay, I'm still wondering about this test though:
Is it valid? Firefox is not eagerly computing the colors at specified value time, though Safari is.
Another open question: what should we do for negative calc
values? From https://w3c.github.io/csswg-drafts/css-values-4/#calc-range:
Parse-time range-checking of values is not performed within math functions, and therefore out-of-range values do not cause the declaration to become invalid. However, the value resulting from an expression must be clamped to the range allowed in the target context. Clamping is performed on computed values to the extent possible, and also on used values if computation was unable to sufficiently simplify the expression to allow range-checking. (Clamping is not performed on specified values.)
This would mean that for something like color-mix(in srgb, red calc(-10%), blue);
, calc(-10%)
will get accepted, then clamped to zero, so the resulting color will be blue. This is what Firefox is doing, Safari rejects the input.
Another open question: what should we do for negative calc values?
Hmm. I thought that was already covered:
Percentages are required to be in the range 0% to 100%. Negative percentages are specifically disallowed.
But then the list of steps for percentage normalization doesn't say what to do if they happen anyway. It needs a new step between 2 and 3 where any value < 0% gets clamped to 0%, and any value > 100% gets clamped to 100%
Another open question: what should we do for negative
calc
values?
This is not something that needs to be defined specifically for color-mix()
, it's the same handling as any other property or function that only allows positive numbers, e.g. padding
or <border-radius>
in inset()
.
Another open question: what should we do for negative
calc
values?This is not something that needs to be defined specifically for
color-mix()
, it's the same handling as any other property or function that only allows positive numbers, e.g.padding
or<border-radius>
ininset()
.
Yes, this is generally covered by the css-values spec which says e.g. calc(-10%) should not be invalid at parse/specified time here even if negative percentages are not allowed, but should be clamped to the allowed range at computed value time.
There is one tricky part that I'm not sure if we have for other properties, and that is that color-mix() can be invalid even when both percentage values are separately within the allowed range. If you have two negative percentages (or 0%), and they are clamped at computed value time, you will end up with two 0% values which is still invalid per spec.
If you have two negative percentages (or 0%), and they are clamped at computed value time, you will end up with two 0% values which is still invalid per spec.
I agree that this case needs to be explicitly specified. I suggest it is treated the same as "both percentages omitted" which results in a 50:50 mix.
it's the same handling as any other property or function that only allows positive numbers, e.g.
padding
or<border-radius>
ininset()
True, although some examples demonstrating this wouldn't hurt.
If you have two negative percentages (or 0%), and they are clamped at computed value time, you will end up with two 0% values which is still invalid per spec.
I agree that this case needs to be explicitly specified. I suggest it is treated the same as "both percentages omitted" which results in a 50:50 mix.
I don't have any strong opinions here.
If you have two negative percentages (or 0%), and they are clamped at computed value time, you will end up with two 0% values which is still invalid per spec.
I agree that this case needs to be explicitly specified. I suggest it is treated the same as "both percentages omitted" which results in a 50:50 mix.
I don't have any strong opinions here.
Another possibility is to make it invalid at computed value time. That would be the first case of values being invalid at computed value time for values not involving var() references.
I can see the case for IACVT. Deliberately omitting both percentages has clear authorial intent (mix these two colors, equally) while two negatives does not.
Looping back to this, was the consensus to make negative values which then get clamped to 0 and sum to 0 IACVT?
https://drafts.csswg.org/css-color-5/#resolving-contrast has some rules to resolve
color-contrast()
values, however I'm not sure they are clear or they match what implementations want or can do.https://github.com/web-platform-tests/wpt/issues/34158 is an example of this, where it seems like WebKit resolves
color-mix()
at parse-time (they don't seem to supportcurrentColor
insidecolor-mix()
).In Gecko, I opted for the approach of keeping
color-mix()
in the specified value, but resolve at computed-value time (except forcurrentColor
which is special of course, but that's not observable anyways becausegetComputedStyle
returns resolved colors).It's clear that some amount of these functions needs to be preserved all the way to computed-value time (system colors), or even used-value time, for
currentColor
.However, it's not clear what amount needs to be preserved at parse-time vs. not. Generally, we preserve stuff at parse-time, (so
element.style.color
would returncolor-mix(red, blue)
for example. But then there's the precedent ofcalc()
where we normalize generally as much as possible.I tend to think preserving the function at parse-time is simpler and maybe less confusing for authors, but I don't particularly mind either way.
cc @weining @svgeesus @lilles