Closed LeaVerou closed 8 months ago
In the NYC F2F in 2022, we discussed defining an MVP of
contrast-color()
that would only returnblack
orwhite
depending on what color text is most readable for the background color passed. I thought we had a resolution on this, but I can’t find it.
The resolutions are in Minutes New York F2F 2022-08-02 Part II: CSS Color and Minutes New York F2F 2022-08-02 Part III: CSS Color .
I think the one you are thinking of might be
RESOLVED: We have an unspecified default, the best available to the UA, which gets updated, only allowed when there aren't any candidates. If you include any candidates, algorithm is mandatory (Issue #7361: color-contrast() default algorithm)
although (relevant to your proposal above) we also have
RESOLVED: Whatever keywords for foreground/background are named, they are are required (Issue #7359)
Thanks @svgeesus, I updated the OP accordingly.
I’m the PM for Web UI at Chrome, my team would be implementing color contrast if it were ready. I would like to get to resolution on this issue sooner than later because it is a high priority for us this year. This is my suggestion about how we could move forward. We don’t yet know the optimal algorithm for color contrast, and I believe we need to find a way to make this an iterative process, so we can start experimenting with it as soon as possible.
TL;DR I’m proposing that we specify an MVP contrast-color() function which has a UA controlled algorithm.
We want to support both user needs and author intent in a way that is performant, usable, accessible, readable, and beautiful. An example of where we've done this by initially specifying UA control is text-wrap: balance
, where we started with only a couple heuristics, but plan to expand and refine over time.
Looking at this diagram, it is clear that there are a lot of cases where WCAG 2.1 can be improved on, however it may take time to find those opportunities and experiment to determine if they work.
If the author specifies the algorithm now, UAs won’t be able to make improvements and up-level the web. However, if we provide a basic color contrast function now, we can always allow more author control over the algorithm in the future. Going the other way around would require each site to manually upgrade, which would take a long time for users to realize the value.
An iterative, UA-first approach would also remove the burden to get everything right up front and instead move us to a more agile process. For example, we could try improvements behind a flag, effectively allowing us to see how that would affect UX across the web.
Yes, initially this would make the property a bit less predictable for the values in the middle of that chart, but the user benefit of being able to iterate in the UA outweighs author control (just for now). I am excited to see how much better we can make contrast-color() given time and iteration.
I propose that we:
To be clearer about what I'm proposing vs what @LeaVerou suggested:
I don't think we should specify white/black text or anything else about how the algorithm for contrast should work, except that it should always be better than WCAG 2.1 requires. It seems like the existing resolution may already be good enough to get started on that? (I'm not sure, I could definitely be reading it wrong? Especially the candidates part.)
RESOLVED: We have an unspecified default, the best available to the UA, which gets updated
Our goal is maximizing readability and that is a nuanced question as I can see from the many open issues on this. We will undoubtedly want to add more to the algorithm over time, and if we go with white/black, I don't see a path to reducing the contrast later, even if it still meets WCAG 2.1. If we leave it up to the UA (for now), we can experiment towards maximum readability and good contrast without an artificial constraint imposed by any particular existing algorithm, other than the floor, provided by WCAG 2.1.
@LeaVerou What syntax that would leave open the possibility of adding additional arguments to this function in the future? Perhaps a basic function that just takes in a color and returns another. Could we later add additional optional parameters to the function when we know more about where author control could be helpful?
I'd like to take all the ideas that have come through so far, and start experimenting with them in the UA, for the moment with the non-color expert author in mind. I realize that could feel like relinquishing a lot of control to the UA, but what I really mean is that I'd like for us to partner in a tight loop to improve the UA algorithm together. I think the v0 we would ship would look a lot like what @LeaVerou proposed. I'm suggesting we wait to put it into a spec until we feel confident that we've done everything we can in the UA to have good outcomes for users needing contrast, even when sites are built by authors who don't understand color.
To summarize for the call, what we need consensus on is:
contrast-color()
function focused around calculating a contrasting text color so we can address the most pressing use case while we figure out the specifics for addressing the more complex use cases?For (2), the two proposals so far are:
black
or white
depending on which one produces the maximum contrast when used as text over the provided color (@leaverou, @fantasai)
The rationale for this is:
black
or white
is more versatile: it can be blended with other colors, made lighter, darker, more transparent etc, to be used in other visual elements as well (e.g. borders and other decorations)The CSS Working Group just discussed [css-color-6] `contrast-color()` MVP in Level 5
, and agreed to the following:
RESOLVED: pursue this approach in level 5
Everything is UA-dependent, including the return value.
The reason I wanted the text color to also be UA dependent is so we could maximize readability rather than contrast. I've seen everyone's thoughts in different threads which left me with the impression that readability is ripe for innovation and experimentation.
Everything is UA-dependent, including the return value.
The reason I wanted the text color to also be UA dependent is so we could maximize readability rather than contrast. I've everyone's thoughts in different threads which left me with the impression that readability is ripe for innovation and experimentation.
Thanks, I’ve added this point to the summary above.
I strongly believe that, following the science, the MVP should be restricted to achromatic colors (black or white, in the limiting case). Here is why:
Studies (Legge 1990) of both people with normal color vision, and people with low vision, have shown that sufficient luminance contrast is the primary factor affecting reading speed, and that adding chromatic contrast does not further increase reading speed. This is true for both those with low vision and those with normal vision:
We found no advantages of color contrast for low-vision reading. For text composed of 6° characters, all low-vision subjects read better with luminance contrast than with color contrast.
Beretta summarized the state of text readability research (as of 2009) as follows:
Indeed, Zuffi et. al. (2009) found that for more muted color combinations, the presence of chromatic contrast (measured as Δab) impaired reading performance, compared to luminance contrast (measured as ΔL) alone:
By using regression analysis we verified that in the first case (“Low Chromatic” group) there is a significant (p-value = 0.003) inverse relationship between reading performance and chromatic contrast; execution times increase as chromatic contrast increases, indicating a penalizing effect of this parameter. In the second case (“High Chromatic” group), on the contrary, the relationship is not significant, and this is consistent with the conclusions of other studies, which found that the chromatic contrast does not improve reading performance when a sufficient luminance contrast is present.
See their Figure 3
Giordano Beretta (2009) Text color polarity blog
G E Legge, G S Rubin (1986) Psychophysics of reading. IV. Wavelength effects in normal and low vision J Opt Soc Am A, 3(1): pp 40-51. abstract
Gordon E. Legge, David H. Parish, Andrew Luebker, and Lee H. Wurm (1990) Psychophysics of reading. XI. Comparing color contrast and luminance contrast. Journal of the Optical Society of America vol 7 issue 10 pp. 2002-2010 https://doi.org/10.1364/JOSAA.7.002002
Silvia Zuffi, Carla Brambilla, Giordano Beretta, Paolo Scala (2009) Understanding the readability of colored text by crowd-sourcing on the Web citation | fulltext PDF
Regarding the transparency issue:
if the MVP is only returning opaque black or opaque white then there is no problem with text transparency. (Obviously it needs to be taken into account for the general case with a list of candidate colors, which can be partially transparent. But that case is also fairly simple, composite the text color onto the background color and use the result to do the contrast calculation).
The CSS Working Group just discussed [css-color-6] `contrast-color()` MVP in Level 5
.
Me, @stubbornella, and a few of our color-related implementors discussed this yesterday.
The plan we'd like to get WG approval for is to, for now, pursue the simplest "output a color that contrasts with this input color" use-case. The other aspects the WG has discussed are important and we want to address them, but we believe we can make valuable incremental progress here without blocking ourselves in the future.
Exact proposal (loosely worded):
contrast-color(<color> max?)
Produces a "very light" or "very dark" color, which will contrast well with the input color. The precise algorithm for determining whether to output a light or dark color is UA-defined, as is the precise color produced. However, the output must be within X distance (delta-E units, presumably?) of white or black, and must be opaque. If max
is specified, the output must be white
or black
. The output must make the same "very light" or "very dark" choice whether max
is specified or not; that is, if it would produce black
when max
is specified, then it must produce a "very dark" color when it's not specified, etc.
This definition allows for some UA intervention and tweaking over time, producing near-black or near-white grays, or mixing in a little bit of the input hue, if the UA determines that would give the best result. By guaranteeing that the color is nearly black or white, we limit the potential for undesirable clashes (even if you mix in some hue, the maximum possible chroma is drastically limited), and limit the space of possible inputs that could produce a dramatically different result in different UAs, or the same UA over time. We believe this should be sufficient to avoid freezing on a particular algorithm and forcing future us to specify it.
If the author wants complete control over how they're tweaking their color, max
gives them assurances of the output, so they can use color-adjust() or color-mix() to very slightly tweak the opacity or mix in a hue of their choice. Or they just get a guaranteed, clean black or white, if that's what they'd prefer.
The CSS Working Group just discussed [css-color-6] `contrast-color()` MVP in Level 5
, and agreed to the following:
RESOLVED: function returns dark/light by default and the 'max' keyword for black/white
So, in your estimation, which measure should we use for the thresholding, and what value feels reasonable for that threshold?
My takeaway from Chris' pad is that things are different for dark and light colors (and they also tend to be different when we're dealing with hues too), so it's hard to define a threshold that won't be too big for some and too small for others 😕
I don't have a conclusion at this stage, just wanted to get a feel for the color differences with the slightly-off whites and blacks you mentioned on the call.
If people want to play around with that example here it is.
Yes, for main content, though there are issues worth discussing for both light and dark mode.
With a bright background, #ffffff
can promote eye blistering fatigue, depending on how bright the display is relative to the eye's adaptation state. Considering that many modern devices easily exceed 1000 nits, visual fatigue is an ever-present problem.
One aspect of fatigue results from viewing high luminance relative to adaptation. If it is caused by a greater bleaching of cone opsins than can be replenished, aka the snow blind effect (this is not actual photokeratitis which is exposure to excess UV, but a loss in sensitivity due to high luminance), or from blue or HEV light, is a subject of continuing study.
There are some rather unfortunately misunderstandings floating around the internet suggesting that text be light grey, or that you don't want "too much contrast". Most of these ideas are bunk. One in particular seems to be sourced from an 2018 article at UXMovement, which is a source of much false or misleading information.
In light mode, text should ideally be black. Feelings of "too much contrast" are due to too much luminance. This problem led to the following:
Something we've been working on, The Paper Reading Experience, is a design guideline for light mode, intended to emulate the nature of reading black ink on diffuse white paper, but presented on a self-illuminated display.
The problem with just using an off white like #eeeeee
is that #eeeeee
will simply become the peak adaptation level within a minute or two, and therefore no different than #ffffff
.
Click for full size
So, to make an "off white" background useful, there needs to be a full white #ffffff
in the peripheral vision in order to anchor the adaptation state to the peak white of the display.
The APC-Readability Criterion site uses this technique. (note this is a draft, and the responsive aspect of the site is a little buggy on cell phones.)
Background: 80% Edge: 100%
Comments are welcome at Paper Reading Experience Discussion
Unlike light mode, there is a level of "too much contrast" in dark mode because of the darker adaptation resulting in wider pupils, and the nature of glare, scatter particularly of point sources, and especially for those with astigmatism. Halation is more problematic in dark mode than in light mode.
We are evaluating a max contrast for dark mode, testing $L^c\ -90$ for text smaller than 24px, and $L^c\ -85$ for larger/bolder text. Thread to discuss maximum contrast.
How dark should the background be in dark mode? IMO that is relative to the surrounding environment. At night, in a dark environment, a full black BG could be fine, provided the text is also dimmer. For a #000000
BG, text is ideally between #cccccc
and #e4e4e4
.
A lighter dark mode BG such as #444444
and #f4f4f4
might be preferred by some for a lighter environment.
Examples:
#000
, but the background is better as off white, 80%-85%, with peripheral elements at #fff
to anchor adaptation.
In the NYC F2F in 2022, we discussed defining an MVP of
contrast-color()
that would only returnblack
orwhite
depending on what color text is most readable for the background color passed. This would address the most common use case where authors have a dynamic color (often user selected) and need to display text on it. Currently authors need to know a lot about a11y and color theory to calculate this reliably, and more often than not the result is suboptmal. You can see an example in this very page:However, the only relevant resolution was this one:
But this only defines defaults, not a path for UAs to implement an MVP of this while we settle the details of the extended syntax. For this to happen, the simpler syntax needs to sit at an earlier level of CSS Color. UAs are extremely keen to ship an MVP for this and have been since 2022, so it's about time we settle on it, without being distracted by the multitude of issues for the extended
color-contrast()
syntax. Out of these issues, only these need to be resolved for this MVP, and none of them is really a roadblock:Apart from those, we'd need to also decide on the syntax, which should be much simpler to do for this than for the extended case, since the point of this is to reduce the number of knobs authors have to understand and tweak and just do the right thing automagically, in line with the TAG principle on balancing simplicity and complxity.
I would propose just
contrast-color(<color>)
in Level 5 (since it's not CR yet) where:accent-color
). Yes, there is a concern that authors might be unhappy with the text color changing from white to black as UAs refine their algorithms, but remember this would only happen in case it improves the result. From conversations with Chrome folks, it appears they are happy to go this route (and have been taking a similar approach for other high level properties, e.g.text-wrap: pretty
), hopefully other implementors share the same sentiment.<color>
is assumed to be background and the function returnswhite
orblack
depending on which one produces the highest contrast for text (choosingwhite
if there’s a tie). Yes, we have a resolution that it should be mandatory to specify whether the color argument is foreground or background, but in doesn't really make a difference here, so it would be unfortunate if authors had to add this noise everywhere.max-contrast-color(<color>)
or justmax-contrast(<color>)
since for every color, eitherwhite
orblack
produce the maximum contrast. Or name it in a way that indicates it returns a foreground/text color.