- From: Chris Lilley via GitHub <noreply@w3.org>
- Date: Thu, 10 Sep 2026 15:39:36 +0000
- To: public-css-archive@w3.org
svgeesus has just created a new issue for https://github.com/w3c/csswg-drafts: == [css-color-4] § 12: at what stage are colors compared, and when are two <color-space>s the same? == [§ 12 Comparing `<color>` Values](https://drafts.csswg.org/css-color-4/#comparing-color-values) leaves two things undetermined. Both are observable, and implementations have diverged. ### 1. What stage of the pipeline does the comparison happen at? [§ 12](https://drafts.csswg.org/css-color-4/#comparing-color-values) says "Given two `<color>` values C1 and C2". `<color>` is a syntactic production, which reads like specified values — but both consumers the section names, `style()` container queries and CSS Transitions, compare computed values. This matters whenever a notation does not survive resolution. [§ 15.1 Resolving sRGB values](https://drafts.csswg.org/css-color-4/#resolving-sRGB-values) resolves `hsl()`, `hwb()`, hex and named colors to *the corresponding sRGB color*, and a missing hue has no counterpart to survive into: ```css hsl(none 0% 50%) /* vs */ rgb(50% 50% 50%) ``` As computed values these are the same sRGB gray with no missing components, so they are equivalent by step 2. As specified values, step 3 is reachable and the missing hue may disqualify the pair. [§ 15.1](https://drafts.csswg.org/css-color-4/#resolving-sRGB-values) does not mention `none` or [missing components](https://drafts.csswg.org/css-color-4/#missing-color-component) at all. ### 2. When are two `<color-space>`s the same? The final paragraph of [§ 12](https://drafts.csswg.org/css-color-4/#comparing-color-values) answers this for the sRGB family, but nothing covers the polar and rectangular forms of the same space: ```css oklch(50% 0 none) /* vs */ oklab(50% 0 0) ``` If `oklab` and `oklch` are different `<color-space>`s, step 3 returns false on the missing hue. If they are one color space in two syntactic forms — which is what they are colorimetrically, and [§ 4.1](https://drafts.csswg.org/css-color-4/#color-syntax) groups `hsl()`, `hwb()`, `lch()` and `oklch()` together as [cylindrical polar](https://drafts.csswg.org/css-color-4/#cylindrical-polar-color) representations — then step 2 applies, the missing hue has no counterpart in the rectangular form, and the answer is true. The two polar families resolve differently, and that difference is not itself in question: | notation | [§ 15](https://drafts.csswg.org/css-color-4/#resolving-color-values) resolves to | polar form survives? | |---|---|---| | `hsl()`, `hwb()` | the corresponding sRGB color ([§ 15.1](https://drafts.csswg.org/css-color-4/#resolving-sRGB-values)) | no | | `lch()` | the corresponding CIE Lab **or LCH** color ([§ 15.2](https://drafts.csswg.org/css-color-4/#resolving-lab-lch-values)) | yes | | `oklch()` | the corresponding Oklab **or OkLCh** color ([§ 15.3](https://drafts.csswg.org/css-color-4/#resolving-oklab-oklch-values)) | yes | The sRGB row is constrained by backward compatibility — `hsl()` has serialized as `rgb()` since CSS Color 3, and content depends on it — whereas the Lab and Oklab families were new enough to preserve the authored form. So this asymmetry is load-bearing and cannot be removed; [§ 12](https://drafts.csswg.org/css-color-4/#comparing-color-values) has to account for it rather than assume it away. [§ 12](https://drafts.csswg.org/css-color-4/#comparing-color-values)'s final paragraph is already the precedent for doing so: it decouples "which `<color-space>` is this compared in" from "what is its computed value", for exactly the family where the two come apart. What is missing is the equivalent statement for `lab()`/`lch()` and `oklab()`/`oklch()`, which can be made without disturbing how those notations resolve or serialize. One consequence worth confirming either way: if the comparison is on computed values, step 1 can never fire for `hsl()` or `hwb()`, since they are no longer cylindrical by then, and [powerless components](https://drafts.csswg.org/css-color-4/#powerless-color-component) would only ever matter for `lch()` and `oklch()`. ### Suggested direction 1. State in [§ 12](https://drafts.csswg.org/css-color-4/#comparing-color-values) which values are compared. If computed, the final paragraph becomes a consequence of [§ 15.1](https://drafts.csswg.org/css-color-4/#resolving-sRGB-values) rather than a rule of its own. 2. Record in [§ 15.1](https://drafts.csswg.org/css-color-4/#resolving-sRGB-values) what becomes of `none`, documenting what implementations already do: a component with an sRGB counterpart keeps its missingness (`rgb(none 128 0)`), one without loses it (`hsl(none 100% 50%)` → `rgb(255 0 0)`). 3. Say whether the polar and rectangular forms of one space are the same `<color-space>` for this comparison, and if so which components are compared. Step 4 already treats `oklab` as the canonical meeting point. ### Implementation status Chromium and Gecko currently disagree with [§ 12](https://drafts.csswg.org/css-color-4/#comparing-color-values) and with each other on adjacent cases, which suggests the section is being read in more than one way: - <https://issues.chromium.org/issues/559142618> — no cross-notation comparison at all - <https://bugzilla.mozilla.org/show_bug.cgi?id=2070595> — step 1 not applied Both engines fail every positive subtest of <https://github.com/web-platform-tests/wpt/pull/62570>, which covers powerless hues within a single color space. Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/14472 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Thursday, 10 September 2026 15:39:37 UTC