Skip to content

[css-color-5] color-contrast() needs resolution logic if 2 or more have the same contrast #4732

Closed

Description

@argyleink

Spec draft
https://drafts.csswg.org/css-color-5/#colorcontrast

Example

foo {
  --bg: hsl(200 50% 80%);
  --purple-in-hsl: hsl(300 100% 25%);
  color: color-contrast(var(--bg) hsl(200 83% 23%), purple, var(--purple-in-hsl));
}

verify contrast scores: [hsl(200 83% 23%), purple, var(--purple-in-hsl)]

Given purple, hsl(200 83% 23%), & hsl(300 100% 25%) all have the same contrast with --bg, which wins? First match, cascade, your idea?

Activity

  1. svgeesus commented on Feb 3, 2020

    @svgeesus
    Collaborator

    Good catch, @argyleink I agree this needs to be specified

    Given that the second parameter to color-contrast is a list of alternatives, then similar to other lists in CSS I suggest that the earliest match wins. In other words the logic is:

    • if the list has one item, it wins
    • if the list has two or more items, the first is the temporary winner but the next takes the winning place if it is better, and so on down the list

    We also need to specify what happens if the first param is not a valid color, or any item of the second param are not valid colors.

    • thus, a later item with the same score as an earlier item will not win.
  2. svgeesus commented on Feb 3, 2020

    @svgeesus
    Collaborator

    @una @LeaVerou should I go ahead and spec "first in list wins" or do you have other ideas on a resolution?

  3. self-assigned this
    on Feb 3, 2020
  4. tabatkins commented on Feb 3, 2020

    @tabatkins
    Member

    Yeah, since there's no further context to decide ties, going with first-wins seems reasonable.

  5. svgeesus commented on Feb 4, 2020

    @svgeesus
    Collaborator

    Not so fast on the closing, Chris :)

    We also need to specify what happens if the first param is not a valid color, or any item of the second param are not valid colors.

  6. svgeesus commented on Feb 4, 2020

    @svgeesus
    Collaborator

    verify contrast scores: [hsl(200 83% 23%), purple, var(--purple-in-hsl)]

    Note that these all give the same contrast of 6.08, when rounded to 3 significant figures as your tool does, @LeaVerou but when a higher precision is used, purple wins. I made that point in the spec text.

  7. argyleink commented on Feb 5, 2020

    @argyleink
    Author

    first wins, i dig it.
    and nice catch on the higher precision contrast score! makes me wonder where the implementers will get their scoring algorithm from and whether or not we need to provide it (or one that works with CIE and offers higher precision) in the spec?

  8. svgeesus commented on Feb 5, 2020

    @svgeesus
    Collaborator

    makes me wonder where the implementers will get their scoring algorithm from

    The algorithm is given in WCAG 2.1 and the inputs are the relative luminances of the two colors being compared.

    In utilities.js I have added that function, for convenience, although the inputs are sRGB only (same as WCAG):

    function contrast(RGB1, RGB2) {
        // return WCAG 2.1 contrast ratio
        // https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio
        // for two sRGB values
        // given as arrays of 0.0 to 1.0
    
        var L1 = sRGB_to_luminance(RGB1);
        var L2 = sRGB_to_luminance(RGB2);
    
        if (L1 > L2) return (L1 + 0.05) / (L2 + 0.05);
        return (L2 + 0.05) / (L1 + 0.05);
    }
    

    I also have a function sRGB_to_luminance(RGB) in utilities.js, primarily to help writing examples.

    Notice that relative luminance is just the Y in CIE XYZ and conversions.js provides sample code to convert any of the predefined colorspaces to XYZ (for the rgb spaces, in two steps: undo gamma correction, then convert linear rgb to XYZ). The same goes for Lab to XYZ (two steps, convert to D50 XYZ then adapt to D65 XYZ) and LCH to XYZ (three steps, first convert LCH to Lab).

    And even for calibrated spaces like CMYK etc, if a color profile is provided.

    It is always just a case of computing two luminances, Y1 and Y2, then doing the simple ratio (with 5% flare compensation).

    Luminance has been defined by an international standard since 1931, we don't need to define it in CSS just document how it is calculated, to help developers.

  9. svgeesus commented on Feb 5, 2020

    @svgeesus
    Collaborator

    I should probably add another contrast example where the color list includes display-p3, prophoto-rgb, and lab and lch values.

  10. argyleink commented on Feb 10, 2020

    @argyleink
    Author

    feels like there's clear resolution on this issue, it's ready to close yeah?

  11. svgeesus commented on Feb 11, 2020

    @svgeesus
    Collaborator

    We also need to specify what happens if the first param is not a valid color, or any item of the second param are not valid colors.

  12. tabatkins commented on Feb 13, 2020

    @tabatkins
    Member

    Both of those cases are "doesn't match the grammar" and thus are invalid, right?

  13. svgeesus commented on Feb 14, 2020

    @svgeesus
    Collaborator

    Yes, I assumed so. Or, if a custom property is involved and the parser can't tell, invalid at computed value time.

    Do we need t say either of those things explicitly or is it just assumed?

  14. tabatkins commented on Feb 20, 2020

    @tabatkins
    Member

    They're just assumed. If you write something into a property that takes <color> that doesn't match the grammar of anything defined under the <color> nonterminal, it's invalid and the appropriate error-handling happens automatically.

  15. svgeesus commented on Mar 3, 2020

    @svgeesus
    Collaborator

    OK in that case this can indeed be closed.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions