Skip to content

<absolute-color-base> not enough anymore #9555

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

Closed
svgeesus opened this issue Nov 2, 2023 · 20 comments
Closed

<absolute-color-base> not enough anymore #9555

svgeesus opened this issue Nov 2, 2023 · 20 comments
Assignees
Labels
css-color-4 Current Work css-color-5 Color modification

Comments

@svgeesus
Copy link
Contributor

svgeesus commented Nov 2, 2023

The notion of <absolute-color-base> was introduced to the grammar of <color> in CSS Color 4 to separate out problematic things like currentColor (which can't be resolved until used-value time and depends on the value of color on that element and its ancestors) or <system-color> which depend on light/dark mode, and forced colors mode

It continued on in CSS Color 5 where it is also used to exclude problematic device-cmyk() (which has no colorimetric basis and might be resolved by an ICC profile or might be an eye-searingly inaccurate naive color conversion

<absolute-color-base> is used directly in the grammar for the override-colors descriptor on @font-palette-values (to exclude currentColor). But there is no good reason to exclude device-cmyk() there.

However, this is no longer sufficient because CSS Color 5 introduces color-mix() and Relative Color Syntax so what used to be a resolvable, colorimetric item like rgb(30% 70% 20%) could now be rgb(from currentColor r g b) or color-mix(in oklab, rgb(30% 70% 20%) 40%, currentColor).

There is still a need to exclude certain problematic color forms for various reasons, but I am now of the opinion that doing this via formal syntax is no longer workable and the exclusion should be case-by-case in prose, instead.

/cc @fantasai @cdoublev @drott @LeaVerou because I have had discussions touching on this in various other issues and would like feedback.

@svgeesus svgeesus added css-color-4 Current Work css-color-5 Color modification labels Nov 2, 2023
@svgeesus
Copy link
Contributor Author

svgeesus commented Nov 2, 2023

So we would have a grammar like

<color> = <color-base> | currentcolor | <system-color> 
<color-base> = <hex-color> | <color-function> | <named-color> | transparent
<color-function> = <rgb()> | <rgba()> |
              <hsl()> | <hsla()> | <hwb()> |
              <lab()> | <lch()> | <oklab()> | <oklch()> |
              <color()> |
              <device-cmyk()> | <color-mix()> | <light-dark()>

@cdoublev
Copy link
Collaborator

cdoublev commented Nov 2, 2023

FWIW, I am fine with flattening color sub-productions and excluding some functions or arguments in some contexts in prose, if this cannot be achieved with basic syntax, which seems hard to achieve here, and also with keeping productions that are neither related to parsing/serialization rules (<color-base>, <color-function>), if this can help defining syntax "families".

@tabatkins
Copy link
Member

Yeah, that sounds appropriate. I'd still have an <absolute-color> production, just actually define it in prose to be the absolute color formats, and relative/mixed colors using absolute colors as inputs.

@svgeesus
Copy link
Contributor Author

svgeesus commented Nov 2, 2023

I'd still have an production, just actually define it in prose to be the absolute color formats, and relative/mixed colors using absolute colors as inputs.

Yup @LeaVerou suggested the same thing to me earlier.

@stiiin
Copy link
Contributor

stiiin commented Jan 12, 2025

I'm not sure what would be the most appropriate place to raise this, but I'm starting to think that the spec phrase

Nor are any of those values used inside <color-mix()> or in relative color syntax.

is not entirely true in implementations.

I wrote a little test (GitHub doesn't let me upload *.html, so *.txt will have to do) and see that both Firefox (128.6.0esr) and Chromium (131.0.6778.264) show the same results:

  • <device-cmyk()> can't be used inside color-mix(), in line with the spec.
  • <system-color> and <light-dark()> can be used inside color-mix(), even though the spec seems to prohibit this behaviour.
  • <contrast-color()> can't be used inside color-mix(), and is marked as "invalid property value". This is in line with the spec, but also odd, given the behaviour of the implementations with the other types of color values. (This was the reason why I started looking into this.)
  • currentColor can be used inside color-mix(). And although I haven't shown it in my test, it's even treated as valid when it's used for the color property ;)

Is this a point where the implementations and specification are drifting apart, or are they behaving as specified (and am I misunderstanding the spec)?

@svgeesus svgeesus reopened this Jan 14, 2025
@svgeesus svgeesus self-assigned this Jan 14, 2025
@cdoublev
Copy link
Collaborator

cdoublev commented Feb 7, 2025

Chrome and Firefox do not currently support device-cymk() and contrast-color(). Therefore only currentcolor, <system-color>, light-dark(), can be tested.

In the relative color syntax, Chrome accepts all relative colors. Firefox only accepts currentcolor.

In override-colors, Chrome and Firefox do not accept relative colors, as specified (and presumably motivated by this comment):

The specified <color> must be an absolute color.

nit: adding "otherwise it is invalid" would be very handy to find it among the syntax rules defined in prose.

I would suspect that any relative color function should not accept relative colors as argument. But both Chrome and Firefox accept any of them in light-dark().

svgeesus added a commit that referenced this issue Feb 7, 2025
@svgeesus
Copy link
Contributor Author

Closing again as the [comment by @cdoublev (https://github.com//issues/9555#issuecomment-2642195433) answers the questions asked, and the one small change to CSS Fonts 4 about override-colors being invalid if the color is not absolute has been made.

@cdoublev
Copy link
Collaborator

cdoublev commented Apr 20, 2025

As described in the op/title, this issue may be considered as fixed, but I see two related issues that may need to be further discussed separately:

  • device-cmyk() in @font-palette-values/override-colors (suggested in the op)
  • colors resolved at used value time or later in color-mix() (implemented in Chrome/FF)
  • colors resolved at used value time or later in RCS (implemented in Chrome, and FF for currentcolor)

I cannot find any related issue open.

Non-absolute color in color-mix() RCS override-colors
currentcolor valid in Chrome/FF valid in Chrome/FF invalid
<system-color> valid in Chrome/FF valid in Chrome invalid
light-dark() valid in Chrome/FF valid in Chrome invalid
contrast-color() NA NA NA
device-cmyk() NA NA NA

Specs currently require all non-absolute colors to be invalid in color-mix(), RCS, override-colors.

@svgeesus
Copy link
Contributor Author

override-colors links to https://drafts.csswg.org/css-color-5/#absolute-color which already excludes device-cmyk() and contrast-color(). What am I missing here.

Also, could you clarify what should be said about colors resolved at used value time?

@cdoublev
Copy link
Collaborator

cdoublev commented Apr 22, 2025

Chrome/FF implementations (cannot speak about Webkit) suggest making exceptions to this (as already reported by @stiiin above):

Nor are any of those values used inside <color-mix()> or in relative color syntax.

And if I understand your comment correctly:

But there is no good reason to exclude device-cmyk() there [in override-colors].

You also suggested allowing device-cmyk() in override-colors.

So I would like to clarify whether these implementations are correct and exceptions should be made to the above restriction, and whether your suggestion is rejected.

@svgeesus
Copy link
Contributor Author

Ah, I see. Yes, my earlier suggestion to allow device-cmyk() in override-colors was not popular and the spec reflects this (it makes override-colors invalid)

@svgeesus
Copy link
Contributor Author

  • currentColor can be used inside color-mix(). And although I haven't shown it in my test, it's even treated as valid when it's used for the color property ;)

Yes, that is correct. From 14.5. Resolving other colors

In the color property, the used value of currentcolor is the resolved inherited value. In any other property, its used value is the used value of the color property on the same element.

@cdoublev
Copy link
Collaborator

cdoublev commented Apr 23, 2025

Ah, I see. Yes, my earlier suggestion to allow device-cmyk() in override-colors was not popular and the spec reflects this (it makes override-colors invalid)

I cannot find the related discussions to understand why, but I have no opinion on this. Alright.

So if currentcolor can be used in color-mix() and RCS, I suggest this change:

- Nor are any of those values used inside <color-mix()> or in relative color syntax.
+ All these values but currentcolor are invalid inside <color-mix()> or in relative color syntax.

Alternatively:

- Nor are any of those values used inside <color-mix()> or in relative color syntax.
+ Nor are any of those values used inside <color-mix()> or in relative color syntax,
+ unless otherwise specified.

With a specific statement below the grammar definition of color-mix() and relative color syntax:

color-mix() accepts absolute colors and currentcolor. Other colors are invalid.

Relative colors accept accepts absolute colors and currentcolor as the origin color. Other colors are invalid.

But I would also like to know if Chrome should not accept them all in these contexts.

@svgeesus
Copy link
Contributor Author

Okay, I think I see the confusion.

In the override-colors descriptor, use of a non-absolute color makes the descriptor invalid. The current text could be understood to mean that the color itself is invalid, and I think that was your interpretation.

Colors which are not absolute are perfectly fine in general, they just require special handling.

For example,

depend on the color mode, which can vary per element. So the result of color-mix() for example will depend on the element on which is is applied.

For example, inside color-mix, if currentColor is used, the procedure to resolve the currentColor value is given

The currentcolor keyword computes to itself.

In the color property, the used value of currentcolor is the resolved inherited value. In any other property, its used value is the used value of the color property on the same element.

in consequence, in 10.1. Resolving color-mix() Values:

If all parameters resolve to the corresponding colors in their respective color spaces, the computed value is the mixed color, in the specified mixing color space, resolved according to CSS Color 4 §  14. Resolving Values. Otherwise (if currentColor was used in the function), the computed value is the color-mix() function with each parameter resolved according to CSS Color 4 §  14. Resolving Values, thus preserving inheritance into child elements.

and similarly in RCS, 10.2. Resolving Relative Color Syntax Values :

If all parameters resolve to the corresponding colors in their respective color spaces, the computed value is the absolute value, in the specified RCS color space, resolved according to CSS Color 4 §  14. Resolving Values.

Otherwise (if currentColor was used in the function), the computed value is the Relative Color Syntax function with the origin parameter resolved according to CSS Color 4 §  14. Resolving Values, thus preserving inheritance into child elements.

I think you were reading an "all non-absolute colors are invalid" into the specification, which was not the intent.

Reviewing that text it is clear that 10.1 and 10.2 were written with primarily currentColor in mind. system-color, light-dark and contrast-color resolve to the corresponding colors in their respective color spaces, so that is fine too.

But we do need an addition to call out the used value of device-cmyk in color-mix(). Probably with an example that shows a 100% mix of a device-cmyk() value results in whatever the fallback color is, not the original color.

And 6. Uncalibrated CMYK Colors: the device-cmyk() Function needs an explicit mention (rather than inferring from omission in 4. Relative Colors ) that device-cmyk() cannot be used in RCS, and that doing so makes the RCS invalid.

svgeesus added a commit that referenced this issue Apr 23, 2025
…e the whole descriptor invalid, not just the individual color #9555
svgeesus added a commit that referenced this issue Apr 23, 2025
@cdoublev
Copy link
Collaborator

In the override-colors descriptor, use of a non-absolute color makes the descriptor invalid.

That was clear to me.

I think you were reading an "all non-absolute colors are invalid" into the specification, which was not the intent.

I am reading "all non-absolute colors are invalid in color-mix() and RCS":

Nor are any of those values used inside <color-mix()> or in relative color syntax.

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

Examples in color-mix():

  • color-mix(in lab, currentcolor, black)
  • color-mix(in lab, CanvasText, black)
  • color-mix(in lab, light-dark(black, black), black)
  • color-mix(in lab, contrast-color(black), black)
  • color-mix(in lab, device-cmyk(0% 0% 0% 0%), black)

Examples in RCS:

  • rgb(from currentcolor 0 0 0)
  • rgb(from CanvasText 0 0 0)
  • rgb(from light-dark(black, black) 0 0 0)
  • rgb(from contrast-color(black) 0 0 0)
  • rgb(from device-cmyk(0% 0% 0% 0%) 0 0 0)

@svgeesus
Copy link
Contributor Author

I am reading "all non-absolute colors are invalid in color-mix() and RCS":

Can you point out exactly where it says that? Because the line you quoted is just one part of the "absolute color" definition.

@cdoublev
Copy link
Collaborator

Quoting it with the full context would be pointless. If this line is not enough, I guess I misinterpreted it, sorry.

@svgeesus
Copy link
Contributor Author

The examples you gave are all valid. They aren't absolute. The value cannot be computed on encountering them; it depends on document context and the value of other properties.

@cdoublev
Copy link
Collaborator

Damn. So the explicit version of this line is:

Nor are any of those values absolute when used inside <color-mix()> or in relative color syntax.

Ok. Sorry for the confusion, again... and thanks for your patience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-color-4 Current Work css-color-5 Color modification
Projects
None yet
Development

No branches or pull requests

4 participants