Skip to content

[css-color-4] Clarify setting "colorful" components to zero when changing a powerless hue component to a missing component #14531

Open

Description

@weinig

In CSS Color 4's section on powerless color components it states:

When changing a powerless hue component to a missing component, the chroma (or other measure of colorfulness, such as saturation in hsl; see analogous components) is set to zero to avoid amplifying floating-point noise. Negative values are not clamped to zero, this value is only set to zero when it is larger than zero but smaller or equal to ε

However, the specific algorithms (both normative and non-normative) don't seem to perform this zeroing.

For Converting Lab or Oklab colors to LCH or OkLCh colors, the algorithm is:

C = sqrt(a^2 + b^2)
if (C > epsilon) H = atan2(b, a) else H is missing
L is the same

To adhere to rule, it should probably be,

C = sqrt(a^2 + b^2)
if (C > epsilon) H = atan2(b, a) else H is missing and C = 0
L is the same

For Converting sRGB Colors to HSL, the relevant part of the algorithm is:

if (sat <= epsilon) {
hue = NaN;
}

and should probably be

if (sat <= epsilon) {
hue = NaN;
sat = 0;
}

I will say, I don't really understand what the HWB code should be given the pseudo-code at the end of https://drafts.csswg.org/css-color-4/#powerless, but some updating https://drafts.csswg.org/css-color-4/#rgb-to-hwb with it would be very helpful.

cc @svgeesus

Activity

  1. romainmenke commented on Sep 28, 2026

    @romainmenke
    Member

    I will say, I don't really understand what the HWB code should be given the pseudo-code at the end of https://drafts.csswg.org/css-color-4/#powerless

    In HWB it is possible to have an achromatic color (W + B equal or greater than 100) that also has a missing W or B.

    So the pseudo code tries to describe how to deal with that.

    If neither is missing, W and B can be normalized by setting B to 100 - W.
    If either is missing, set the non-missing one to 100.

    For hwb at least it is important to only do these steps when between the epsilon and 100 as values larger than 100 are possible.

    In my implementation I also only set s or c to zero when it has a value between zero and epsilon. Negative values (if those are even possible) are preserved.

    If there is a better way to describe this, please make a suggestion :)

  2. weinig commented on Sep 28, 2026

    @weinig
    ContributorAuthor

    Well, the suggestion is for the code snippet that describes the conversion for HWB in the HWB section to include the logic.

  3. weinig commented on Sep 28, 2026

    @weinig
    ContributorAuthor

    I'm confused how W + B > 100 can be true when W or B is missing. Is the premise that if one is missing the other is itself > 100 so when added to 0 (the resolved missing value) it is still greater than 100?

  4. romainmenke commented on Sep 28, 2026

    @romainmenke
    Member

    The pseudo code is not limited to cases where either is missing.
    e.g. hsl(from hwb(180 100% 25%) h s l) has H + B > 100.

  5. weinig commented on Sep 28, 2026

    @weinig
    ContributorAuthor

    Whatever the rules, let’s add them to the conversion sample.

  6. self-assigned this
    on Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions