w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.44k stars 657 forks source link

[css-color] color-contrast() should support ranges of candidate colors, not just discrete color candidates #7360

Open LeaVerou opened 2 years ago

LeaVerou commented 2 years ago

When designers are picking colors to pass a certain contrast ratio, they usually adjust a given coordinate, in a given color space (usually lightness). The current color-contrast() syntax only allows providing specific candidate colors, so I worry we will see a lot of this:

background: var(--color);
color: color-contrast(var(--color) vs 
    lch(from var(--color) 100% c h),
    lch(from var(--color)  90% c h),
    lch(from var(--color)  80% c h),
    lch(from var(--color)  70% c h),
    lch(from var(--color)  60% c h),
    lch(from var(--color)  50% c h),
    lch(from var(--color)  40% c h),
    lch(from var(--color)  30% c h),
    lch(from var(--color)  20% c h),
    lch(from var(--color)  10% c h),
    lch(from var(--color)   0% c h)
);

It would be good if there was a syntax to provide the candidate colors as a range, either by reusing <gradient>, or with a watered down microsyntax:

The range would be considered ordered, and browsers would return the first color in the range that passes the target contrast (which they may decide to calculate via binary search). It may make things simpler if ranges can only be from one color to another color.

(Issue filed following breakout discussions between @svgeesus, @fantasai, @argyleink and myself)

BillGoldstein commented 2 years ago

Considering there's been some WCAG3 discussion of maximum contrasts, too, e.g for large text...so as not to burn one's retinas :)

Maybe more than a single range syntax might be appropriate. Think some along the lines of min(), max(), minmax(), maxmin(), and clamp(). In the clamp(min, preferred, max) maybe even mid() for preferred.

Also perhaps consider a "by" increment, and or a "using" named-curve.

Feel free to separate any/all of these into their own issues.

BillGoldstein commented 2 years ago

Though not in color-6, some sort of element-level font-size query is also needed.

Myndex commented 2 years ago

Hi Bill @BillGoldstein

...some WCAG3 discussion of maximum contrasts...

Yes, currently testing a maximum APCA contrast of what is currently calculated as Lc 90, this is on the live SAPC development tool along with a spread of use-case lookups.

There are a variety of factors that make a normative guideline for maximum contrast tricky:

So, at the moment, Lc 90 is an advisory maximum, especially in dark mode. But a better advisory MIGHT be, limit the color to no brighter than the equivalent of about #e6e6e6

A related advisory is for light mode, to keep the background under text to less than about #e6e6e6 as well.

Your mileage may vary, these values are under investigation.

Here's a visual example of some of the factors:

New Eye Strain 2022
css-meeting-bot commented 2 years ago

The CSS Working Group just discussed Ranges of Candidate Colors, and agreed to the following:

The full IRC log of that discussion <fantasai> Topic: Ranges of Candidate Colors
<lea> github: https://github.com/w3c/csswg-drafts/issues/7360
<emilio> lea: there's a discontinuity between how designers design UI and how the contrast-color() function works
<emilio> ... they often have a base color and adjust coordinates (usually lightness) to get sufficient contrast
<emilio> ... right now it's possible but you'd need to provide a bunch of colors to simulate a range
<emilio> ... it'd be nice if you could simplify that usage
<emilio> ... not sure if it would need special syntax, or even if we want to do this
<astearns> ack dbaron
<emilio> ... we might want to punt on it and do it only if people actually do this
<emilio> dbaron: when you suggested syntax, before you said gradient my initial reaction was to use the interpolation syntax
<lea> q?
<emilio> ... I think you could reuse the interpolation syntax without specifying the end
<emilio> ... it's basically gradient without direction / radial stuff
<emilio> ... other thought is that this is difficult to explain with multiple contrast functions
<lea> q+
<emilio> ... if you specify something that's a range of color we specify the order in which you process them in
<emilio> q+
<astearns> ack lea
<TabAtkins> q+
<emilio> lea: I think before we dive down into details we should decide if we want to pursue this
<emilio> ... what that syntax would look like is secondary
<astearns> ack emilio
<fantasai> emilio: I think I'd rather act on it for now
<fantasai> emilio: there are a bunch of things to figure out, e.g. what are the steps you use for lightness?
<fantasai> emilio: what's the resolution of all the colors you try?
<fantasai> emilio: you may try 1000s of colors to find somehting
<fantasai> emilio: seems a bit unpredictable, perf-wise
<lea> q+
<fantasai> emilio: I guess you can binary search, maybe?
<astearns> evaluating all the colors for multiple algorithms seems expensive
<fantasai> emilio: assuming contrast is alwasy increasing or decreasing
<lea> q-
<fantasai> emilio: so unless we find ppl actually doing this,
<dbaron> yeah, I think you can't assume that contrast is always increasing/decreasing
<fantasai> emilio: if you pass 1000 colors, then worst case you evaluate 1000 colors
<fantasai> emilio: For now I'd rather defer this
<fantasai> emilio: I'd rather get the bits we know we want right, and then if we want to extend, we can always do it
<astearns> ack TabAtkins
<emilio> TabAtkins: you can't assume contrast is monotonic if you interpolate hue
<emilio> ... so sampling frequency becomes important
<lea> I actually agree
<fantasai> s/rather act/rather punt/
<emilio> ... so I say we punt for now
<lea> RESOLVED: punt for now, revisit later
<lea> github: https://github.com/w3c/csswg-drafts/issues/5153
<emilio> github: https://github.com/w3c/csswg-drafts/issues/7360
danburzo commented 1 year ago

Color ranges, specifically using interpolation syntax with which authors will be familiar from gradients, sound like a neat way to derive a given color to achieve sufficient contrast from the base color (also captured in https://github.com/w3c/csswg-drafts/issues/5153).

Given there can't be any assumptions about the monotonicity of contrast, so binary search is unhelpful, would it make sense to allow authors to define the number of samples the range computes to, with a default that makes it reasonable to evaluate the list from start to end against one or more contrast targets? And possibly an upper limit so author's can't inadvertently degrade performance on less powerful devices?

Something along the lines of:

range(<number>? <interpolation-method>, <color>#)