-
Notifications
You must be signed in to change notification settings - Fork 641
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] How to handle infinite values in color functions? #10507
Comments
I agree that coercing values to infinity is going to cause no end of problems with color math; most color spaces are not designed to cope with such extreme values. @tabatkins why are we doing this, again?
For color spaces are clamped, yes. Most are not, including I just re-opened #8629 because the WG discussion apparently consisted of @tabatkins asserting that it was fine (for |
Not sure if this is applicable to browser implementations but I found that clamping to a really large value gives good results : https://github.com/csstools/postcss-plugins/blob/20ccaebde3de250e858adbbd3d519b01b7cf5304/packages/css-color-parser/src/functions/hsl-normalize-channel-values.ts#L111 Having a really large but finite value makes the color math work as expected. |
Unless otherwise specified, color channel values are not clamped, which applies to values produced by math functions, which can be infinite.
Infinite color channel values produce
NaN
in most conversion functions.Specifically...
color(srgb-linear) -> color(xyz-d65)
color(xyz-d50) -> color(xyz-d65)
color(xyz-d65) -> color(srgb-linear)
x
andy
are the same infinitex
/y
andz
are infinitecolor(xyz-d50) -> lab()
x
andy
are the same infinitey
andz
are the same infinitecolor(xyz-d65) -> color(xyz-d50)
x
andy
are infinitey
andz
are infinitex
andz
are the same infinitecolor(xyz-d65) -> oklab()
oklab() -> color(xyz-d65)
rgb() -> hsl()
hsl() -> rgb()
s
is infinite andl
is 0/100l
is infinitehwb() -> rgb()
w
is infiniteb
is -Infinitylab() -> color(xyz-d50)
l
is infinite anda
is the opposite infinitel
andb
are the same infinitelch() -> lab()
oklch() -> oklab()
c
is infinite andh
is 0This CodePen allows to play with conversion functions, which have comments for
NaN
cases.In
colorjs.io@0.5.1
,NaN
seems to be replaced bynone
, which seems incorrect:Clarification on how to handle infinite values has already been asked in #8629, which was resolved with no further change because if you put an infinite calculation into an rgba(), the behavior is well-defined: clamp to the allowed range.
At least, this is not true for some channels of other color functions than
rgb()
, and for relative colors.Following this comment, I tried to guess the color resulting from a color function specified with one infinite channel value. Since I am personally only interested by serialized values, I only did it for
hsl() -> rgb()
andhwb() -> rgb()
, but it should presumably be done for all conversions producingNaN
.When converting
hsl()
torgb()
andsaturation
is+Infinity
or-Infinity
: [...]l === 0
,r
,g
,b
, are0
l < 0
, same as whenl > 0
but with inverted infinite signsl > 0
:h
r
g
b
330 < h < 30
+Infinity
-Infinity
-Infinity
h === 30
+Infinity
l
-Infinity
30 < h < 90
+Infinity
+Infinity
-Infinity
h === 90
l
+Infinity
-Infinity
90 < h < 150
-Infinity
+Infinity
-Infinity
h === 150
-Infinity
+Infinity
l
150 < h < 210
-Infinity
+Infinity
+Infinity
h === 210
-Infinity
l
+Infinity
210 < h < 270
-Infinity
-Infinity
+Infinity
h === 270
l
-Infinity
+Infinity
270 < h < 330
+Infinity
-Infinity
+Infinity
h === 330
+Infinity
-Infinity
l
When converting
hsl()
torgb()
andl === +Infinity
:-100 <= saturation <= 100
,r
,g
,b
, are+Infinity
saturation < -100
, same assaturation > 100
but with inverted infinite signssaturation > 100
,r
,g
,b
, are+Infinity
/-Infinity
depending onsaturation
andh
h
h
interval values depend onsaturation
r
/g
/b
has a different signWhen converting
hsl()
torgb()
andl === -Infinity
:-100 <= saturation <= 100
,r
,g
,b
, are-Infinity
saturation < -100
orsaturation > 100
, same as whenlightness === +Infinity
but with different intervalsLet's skip
hwb() -> rgb()
because it becomes more complicated when more than one channel value is infinite.For example, when
a === 0
,z
tends towards+Infinity
whenl
tends towards+Infinity
, butz
tends towards-Infinity
whenb
also tends towards+Infinity
. Shouldz
be0
? Should some "precedence" between channel values be defined?Note that channel values do not always tend linearly towards an infinite value:
rgb(from hsl(0 -99 calc(infinity)) r g b)
would resolve tocolor(srgb calc(infinity) calc(infinity) calc(infinity))
rgb(from hsl(0 -101 calc(infinity)) r g b)
would resolve tocolor(srgb calc(infinity) calc(-infinity) calc(-infinity))
Am I missing something?
The text was updated successfully, but these errors were encountered: