I’m trying to understand none
vs 0
in CSS color functions by creating some visual examples in CodePen. My current understanding is that, at least in practical terms, none
and 0
are equivalent except when interpolating between colors of different spaces. When setting the value for a single, static color, none and zero should produce the same result on screen. See the MDN docs here.
But I see at least one exception to this, where zero outputs color and none outputs black. These two values produce visibly different results on screen:
lch(none 90 0)
vs lch(0 90 0)
div {
display:flex;
flex-grow:1;
height:50px;
}
<div>
<div style="background-color:lch(none 90 90);"></div>
<div style="background-color:lch(0 90 90);"></div>
</div>
<div>
<div style="background-color:lab(none 90 90);"></div>
<div style="background-color:lab(0 90 90);"></div>
</div>
Same for lab()
, which shares the lightness parameter. But it doesn’t apply to the hue in lch()
, at least not in Chrome. In Firefox setting hue to none sets the output to black, so one of them is wrong…
This example indicates that none and zero are different beyond interpolating between two separate colors. Can someone please clarify that, or point me to some docs that explain it for dummies like me?
Also, what are some specific examples where interpolating between two colors produces different results with none
vs 0
? I am using linear-gradient()
as my interpolater for test purposes, and I am having trouble finding cases where none
vs 0
makes a difference in the interpolation of a linear gradient.
Edit: after posting this question I saw that the example snippet displays differently in Chrome vs Firefox – the left and right sides visually (none
vs 0
in the CSS) are flipped between the two browsers.
2
Answers
I opened a discussion at github/color.js to see if anyone there could provide more definitive answers:
https://github.com/color-js/color.js/discussions/495
To summarize the response there:
a) Yes, for single color values,
none
and0
should produce the same results on screen.b) Firefox handles
none
incorrectly (no one on Bugzilla has responded to my bug there yet).c) Chrome and Safari use clipping aka clamping instead of gamut mapping, and the snippet in my question should not show black at all. Safari gets this right, but Chrome displays black for
0
, which means it doesn't matchnone
, which means it's incorrect. So no, not all the rectangles should be black, but they should all be the same on the left and right sides, i.e. the same fornone
vs0
. Chrome has two "fixed" issues relating to this (https://issues.chromium.org/issues/40265669 and https://issues.chromium.org/issues/40262403) and I have commented there prior to submitting a new bug.If you want to dig deeper regarding CSS handling of lightness, see this w3c/csswg-drafts discussion:
https://github.com/w3c/csswg-drafts/issues/8794
Thanks to @wacton and @gre_gor for chipping in. I'm not marking any answer as "accepted", at least not yet. This is messy, relatively new stuff for the browsers, messier than I had anticipated based on the documentation available.
In this case Firefox is incorrect;
lch(0% 90 90)
should produce black according to the CSS specifications. You can also see that Firefox and Safari are failing the LCH test that should generate a black square, and instead generates a red colour.It’s not clear to me what the browser should do when using
none
butlch(none 90 90)
generating a red colour is understandable:LCH [0, 90, 90]
with D50 reference white isRGB [42, -5, -73]
RGB [42, 0, 0]
or#2a0000
LAB [0, 90, 90]
with D50 reference white isRGB [97, -50, -72]
which becomesRGB [97, 0, 0]
or#610000
For some reason Firefox is treating
none
as "no lightness" instead of "unspecified", and ignoring that "0% lightness" should be treated as black.