Skip to content

[css-color] Clarification needed on how missing alpha components flow through relative color syntax for hsl/hwb #10254

Closed

Description

@weinig

In the WPT test, css/css-color/parsing/color-computed-relative-color.html, there are a few examples I don't quite understand and can't figure out which language in the spec dictate them.

One is:

fuzzy_test_computed_color(`hsl(from rebeccapurple none none none / none)`, `color(srgb 0 0 0 / none)`)

What allows the alpha value to be passed through as none?

My understand here of the operations performed is:

  1. rebeccapurple converted to hsl() [hsl(270 50% 40%)]
  2. Relative color is resolved via channel arguments to hsl(none none none / none)
  3. hsl(none none none / none) is converted to color(srgb) for serialization, resolving all missing components to 0 [color(srgb 0 0 0 / 0)] (https://drafts.csswg.org/css-color-5/#serial-relative-color)

Is the intention for that last conversion (from hsl() to color(srgb)) to carry forward analogous component missing values?

Somewhat perplexingly (and perhaps just an error in the test), the corresponding test css/css-color/parsing/color-valid-relative-color has a similar example.

fuzzy_test_valid_color(`${hslFunction}(from rebeccapurple none none none / none)`, `color(srgb 0 0 0 / 0)`);

My expectation is that they should at least expect the same result.

Similarly, what would expect for missing components in the origin.

color: hsl(from hsl(none none none / none) h s l / alpha);
color: hsl(from hsl(none none none / none) h s l);

Activity

  1. svgeesus commented on Apr 26, 2024

    @svgeesus
    Collaborator

    I think this is from 4.1. Processing Model for Relative Colors :

    If the alpha value of the relative color is omitted, it defaults to that of the origin color (rather than defaulting to 100%, as it does in the absolute syntax).

    Missing components are handled the same way as with CSS Color 4 § 12.2 Interpolating with Missing Components: the origin colorspace and the relative function colorspace are checked for analogous components which are then carried forward as missing.

    Aha! It is implied, but not directly stated, that alpha is analogous to alpha.

  2. svgeesus commented on Apr 26, 2024

    @svgeesus
    Collaborator

    If you agree, then I can add alpha to 12.2. Interpolating with Missing Components

  3. svgeesus commented on Apr 26, 2024

    @svgeesus
    Collaborator

    Is the intention for that last conversion (from hsl() to color(srgb)) to carry forward analogous component missing values?

    I'm not fully sure on that point.

  4. weinig commented on Apr 27, 2024

    @weinig
    ContributorAuthor

    I totally agree that adding something to 12.2. Interpolating with Missing Components that says alpha is analogous to alpha would be great.

    To restate what is probably obvious though, the bigger issue on this one is should the conversion from HSL()/HWB() to color(srgb) done for serialization be a "normal conversion" or should it be a "conversion that carries forward analogous component missing values"?

  5. weinig commented on Apr 27, 2024

    @weinig
    ContributorAuthor

    I thought a bit more about this and I think preserving the NaN (that is, using the "carries forward analogous component missing values" conversion) for alpha is better than not.

    My argument is there really isn't any value in converting it to 0 here. As much as possible, serialization tries to preserve as much information as possible, and since we can preserve this, why not. (It also seems to be what Chrome does).

    One things this does is beg the question, should all conversions between color spaces carry forward analogous missing components? In what cases would it not be what you want?

  6. romainmenke commented on Apr 27, 2024

    @romainmenke
    Member

    Is there any part of the specification that indicates that you shouldn't always carry forward analogous missing components during conversions between color spaces?

    I thought this was always required.

  7. weinig commented on Apr 27, 2024

    @weinig
    ContributorAuthor

    Is there any part of the specification that indicates that you shouldn't always carry forward analogous missing components during conversions between color spaces?

    I thought this was always required.

    Section 4.4 is pretty explicit.

    For all other purposes, a missing component behaves as a zero value, in the appropriate unit for that component: 0, 0%, or 0deg. This includes rendering the color directly, converting it to another color space, performing computations on the color component values, etc.

    https://www.w3.org/TR/css-color-4/#missing

  8. weinig commented on Apr 27, 2024

    @weinig
    ContributorAuthor

    And since interpolation calls it out as a separate step, I think the implication is that if an algorithm wants carrying forward, it needs to call it out.

  9. romainmenke commented on Apr 28, 2024

    @romainmenke
    Member

    Ah, indeed!

    The intention is to preserve missing components / none as much as possible.

    So if there are algorithms where it isn't stated and where it could be preserved, then we should change that.

    The serialization as color(srgb) for specific cases is problematic when trying to preserve missing components / none.

    It doesn't currently state that carry forward should happen. But it also makes carry forward impossible for non-alpha components when the src and dest aren't both in srgb to begin with.

  10. romainmenke commented on Apr 28, 2024

    @romainmenke
    Member

    If you agree, then I can add alpha to 12.2. Interpolating with Missing Components

    https://codepen.io/romainmenke/pen/LYvvNrb

    This would also affect interpolation but there isn't any interop for none alpha.
    Chrome threats none in alpha during interpolation as the alpha of the other color. Safari and Firefox do not.

  11. 19 remaining items

  12. svgeesus commented on Jan 27, 2026

    @svgeesus
    Collaborator

    This affects rgb(), hsl() because currently these serialize in legacy syntax "for historical reasons". Should also affect hwb()

  13. css-meeting-bot commented on Jan 27, 2026

    @css-meeting-bot
    Member

    The CSS Working Group just discussed [css-color] Clarification needed on how missing alpha components flow through relative color syntax for hsl/hwb, and agreed to the following:

    • RESOLVED: if 'none' is used in hsl and hwb, we serialize with slashes and none; and for rgb, we serialize with color function
    The full IRC log of that discussion <ChrisL> q+
    <astearns> ack ChrisL
    <dholbert> ChrisL: rgb and hsl serialize as legacy syntax, for compat/historical reasons
    <weinig> q+
    <dholbert> ChrisL: so they can't use the word 'none'
    <dholbert> ChrisL: people have suggested that they serialize with modern syntax which does include 'none'
    <astearns> ack weinig
    <dholbert> ChrisL: let's resolve on that
    <dholbert> weinig: in webkit we implement something a bit different
    <dholbert> weinig: we serialize as hsl, and none is preserved, if you happen to use 'none'
    <dholbert> weinig: so we pull legacy colors out of legacy prison if they happen to use 'none'
    <TabAtkins> +1 to this
    <dholbert> weinig: if you're using modern keywords, then they're not legacy colors anymore, so we're not bound by compatibility
    <TabAtkins> that's def where i thought Chris was gonna go, i was surprised by the color() swerve
    <dholbert> weinig: so if you use none in rgb, we should serialize them as-is
    <romain> present-
    <dholbert> ChrisL/ weinig : if we did conversion to srgb, all the nones would have to be resolved to 0
    <dholbert> ChrisL: I like what weinig said better than my proposal
    <dholbert> ChrisL: proposal is to serialize with modern syntax, with the slashes
    <dholbert> emilio: I think it would be preferable to serialize with color() to avoid introducing a third format that authors need to deal with
    <dholbert> ChrisL: the advantage is if you have a 'none' hue, then you can preserve that
    <dholbert> ChrisL: whereas if you serialize to srgb, you have to convert it to 0
    <dholbert> weinig: another reason this is straightforward: to make interpolation between hsl()'s work well... once you have 'none' in them, we internally keep them as hsl all the way through
    <dholbert> so it doesn't affect the optimizations that engines have where hsls without none can be converted to 32-bit int
    <dholbert> emilio: I guess the alternative would be to add a color-hsl() sort of thing...
    <dholbert> ChrisL: I don't really like that
    <dholbert> emilio: vs. legacy hsl... that might be more consistent?
    <dholbert> ChrisL: it'd be modeled after hwb maybe
    <dholbert> weinig: I don't think that's true; I think hwb follows the hsl pattern
    <dholbert> weinig: we've been shipping this in webkit
    <dholbert> emilio: I agree we need a new serialization either way. Either you convert to rgb, or... Also, for colors that do have the color() function, if you specify 'none' in rgb, we have to decide whether to serialize with slashes or not
    <dholbert> ChrisL: my point from hwb is that it *only* uses slash syntax
    <dholbert> emilio: but it only serializes as rgb, so engines convert it
    <dholbert> emilio: my only concern with doing what's proposed is that there's a lot of parsing on the web that assumes rgb will serialize with commas
    <dholbert> emilio: but on the other hand this scenario is an edge case and so pages probably wouldn't trip over this accidentally
    <dholbert> emilio: but authors need to be prepared to parse a third syntax
    <dholbert> emilio: this is a weak argument... I'm fine
    <dholbert> weinig: authors have to handle a lot of other syntaxes as well, yeah
    <dholbert> emilio: I'm fine with what weinig proposed
    <dholbert> emilio: it's effectively the same as serializing with color and adding a color-hsl thing; it's about the same amount of work
    <dholbert> emilio: it's weird that some colors cannot be specified with color(), but that ship has sailed
    <dholbert> astearns: so hsl, rgb, and hwb colors... if 'none' is used, then we serialize the color as-specified?
    <dholbert> ChrisL: we serialize using a modern syntax which does not yet exist, with hsl(...) with slashes and allows the word 'none'
    <dholbert> emilio: the other weird thing is that for rgb, that would introduce 3 syntaxes when we can get away with 2
    <dholbert> ChrisL: do we need it for rgb?
    <dholbert> emilio: yeah, to preserve 'none'
    <dholbert> emilio: in gecko, if you specify 'none' in alpha for rgb, we serialize with 0
    <dholbert> and commas
    <emilio> rgb(100 100 0 / none) -> color(srgb, ...)
    <emilio> hsl(100 100 0 / none) -> hsl(100 100 0 / none)
    <dholbert> emilio: so we should serialize like that^ ?
    <dholbert> ChrisL: yes
    <dholbert> emilio: I think that's fine
    <ChrisL> and hsl(none 100 0) similarly preserves none
    <dholbert> astearns: proposed resolution: if none is used, we serialize like that
    <ChrisL> q+
    <dholbert> emilio: does webkit do this?
    <astearns> ack ChrisL
    <dholbert> weinig: I'll check
    <dholbert> ChrisL: authors can use this syntax too, right?
    <dholbert> emilio: yeah
    <dholbert> weinig: this round-trips, yeah. that's the most important property to preserve
    <dholbert> PROPOSED: if 'none' is used in colors, we serialize with slashes and none
    <dholbert> PROPOSED: if 'none' is used in hsl and hwb, we serialize with slashes and none; and for rgb, we serialize with color function
    <TabAtkins> I don't know why we're doing this, but I don't care.
    <dholbert> emilio: alternatively we could add color-hsl
    <dholbert> weinig: but then color-oklab, etc
    <emilio> s/color-hsl/color(hsl, ...)
    <dholbert> RESOLVED: if 'none' is used in hsl and hwb, we serialize with slashes and none; and for rgb, we serialize with color function
    <dholbert> weinig: this isn't specific to 'alpha', right?
    <dholbert> ChrisL, emilio : right
    <dholbert> astearns: done with morning session. lunch time
  14. weinig commented on Jan 28, 2026

    @weinig
    ContributorAuthor

    It occurred to me after the discussion that the proposal is very close (if not identical) to what we have for relative color syntax origin color serialization (https://drafts.csswg.org/css-color-5/#serial-origin-color), including preserving hsl()/hwb(). Re-using some of that language will probably make specifying this easier.

  15. cdoublev commented on May 3, 2026

    @cdoublev
    Collaborator

    Based on the last changes, I do not know how rgb(from red 0 none 0) should serialize as a component of a declared value.

  16. romainmenke commented on Oct 24, 2026

    @romainmenke
    Member

    I think we now have sufficient test coverage for this issue through https://github.com/web-platform-tests/wpt/blob/b6bb7b1108e604b3b2cc29329bc8ceae9fd48109/css/css-color/parsing/color-computed-none.html

    I've added a few more in: web-platform-tests/wpt#64150, just to be sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions