-
Notifications
You must be signed in to change notification settings - Fork 747
Description
(This came out of my comment here: #10151 (comment) and subsequent comments)
The spec is currently unclear about this, though @svgeesus made the case that this is editorial. @romainmenke thinks it's a substantive change. Regardless, we need to fix it ASAP to avoid web compat roadblocks.
Currently, css-color-4 is a little unclear on what happens with none
values in authorland calculations, and implementations are currently converting none
to 0
if used in calc()
and other math functions, which comes up a lot in Relative Color Syntax. This was never our intent, the only reason converting none
to 0
exists is that we don't want to be exposing color space conversion math, and/or sometimes you literally need to actually display a color that includes none
components so you need to do something.
Even when converting to different color spaces, the spec already includes the concept of analogous components, to minimize none
→ 0
conversions, and in #10210 I proposed expanding it a bit.
Note that while none
was originally conceived to express achromatic colors and the chroma of white & black, it is actually useful way beyond that, as it allows expressing parameterizable colors, in a way that decouples the calculation from the color (unlike RCS which requires them both at the same time). You only specify the bits that don't change (e.g. hue), leave the rest none
, and let normal CSS operations take their course. E.g. interpolating any (polar) color with oklch(calc(none - 0.4) none none)
interpolates with a darker version of that color. Sure, you can do all these things with pure RCS, but this decouples the parameter from the modification, so you don't even need to know what you’re interpolating with, it just works.
Converting to 0
if used in calculations serves no purpose other than simplifying implementations, reduces none
’s usefulness in creating dynamic colors that can be passed around, and introduces several problems:
- Discontinuity since e.g.
h
andcalc(h)
are not the same, - It makes browser interpolation magic compared to what authors can do with
calc()
or evencalc-mix()
+ RCS. - Disregards author intent
I propose we introduce the concept of none
-containing component and clarify that:
- Calculations preserve
none
. Meaning,calc(h + 20)
in RCS would becomecalc(none + 20)
. Ifh
is already an expression containingnone
, it can be simplified, but only in ways that do not alter its meaning. E.g. ifh
iscalc(none - 10)
,calc(h + 20)
can becomecalc(none + 10)
but can also just staycalc(calc(h - 10) + 20)
orcalc(h - 10 + 20)
. - Interpolation operations (
color-mix()
,calc-mix()
, gradients etc) resolvenone
to the other component if the other component is notnone
-containing. If the other component isnone
-containing, they resolve to acalc-mix()
expression containing both values. E.g. interpolating between a chroma ofnone
and a chroma ofclamp(.1, none, .2)
at 50% would producecalc-mix(50%, none, clamp(.1, none, .2))
. If this color is later interpolated with a color that has a chroma of 0.15, thenone
s would become 0.15, so the component would becomecalc-mix(50%, 0.15, clamp(.1, 0.15, .2))
= 0.15. - Authors should also be able to specify things like
clamp(50, none, 70)
directly.
One thing we need to sort out is what is the precedence is when a function also accepts none
is used in color components. E.g. we recently resolved to allow none
for the upper and lower bound of clamp()
. In those cases, what does none
mean when used in a color component? I would vote for giving precedence to the color-related meaning of none
since that serves a unique purpose, whereas none
in other places is is simply syntactic sugar.