Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-color-6] color-contrast() should take transparency into account #7358

Open
LeaVerou opened this issue Jun 14, 2022 · 23 comments
Open

[css-color-6] color-contrast() should take transparency into account #7358

LeaVerou opened this issue Jun 14, 2022 · 23 comments
Labels
a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. css-color-6

Comments

@LeaVerou
Copy link
Member

LeaVerou commented Jun 14, 2022

In the current draft, transparency is ignored when calculating contrast, because it was ignored in WCAG 2.1 as there were no non-opaque colors then.

However, this could result in completely incorrect results.

Consider this example: color-contrast(white vs rgb(0 0 0 / .1), gray). Because transparency is ignored, it would pick rgb(0 0 0 / .1) as most contrasting, which produces this result:

image

whereas picking gray would have produced this much more legible result:

image

At the very least, UAs should perform alpha blending of background and foreground (see #7359 ). This would be sufficient when the background is opaque, but it does not solve the problem when the background is also semi-transparent. Ideally, UAs would calculate a range of contrasts and a color would be deemed a winner IFF the minimum possible contrast also passes the desired level (I did some work on calculating said range in WCAG 2.1 10 years ago, not sure if there's a better method these days)

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


Resolutions

Aug 2, 2022

  • RESOLVED: When calculating color contrast between pairs of semi transparent colors, if the background is opaque, UAs should alpha blend the foreground on the background and use that as the foreground color. If the background is also semi-transparent, it would be alpha blended first with an opaque version of the foreground
  • RESOLVED: Amend previous resolution, the canvas color in previous resolution is TBD
  • RESOLVED: (rather than opaque version of foreground)
@LeaVerou LeaVerou added css-color-5 Color modification css-color-6 a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. labels Jun 14, 2022
@svgeesus svgeesus removed the css-color-5 Color modification label Jun 15, 2022
@argyleink
Copy link
Contributor

this is such a good point and really nice example of the problem space.

the browser is uniquely positioned to alpha blend, but you're right that how far can that really go? if the 1st parameter was considered the "background", the UA could play out a subtree layout (hopefully a short as it can be) that finds the nearest opaque color for use in alpha blending insomuch to compare the list of colors to. transparent foreground colors are then alpha blended against that subtree composited opaque color result. but just because the browser can, maybe it's too much to ask? there's gotta be a better way.

@tabatkins
Copy link
Member

I suspect the most reliable answer is indeed to assume the first color is a bg and the list is choosing a fg color, do alpha blending if the fg colors are transparent, and do a range if the bg color is transparent. If our assumptions about fg/bg are opposite the actual usage the numbers would end up being different, but not too much iiuc.

@svgeesus
Copy link
Contributor

assume the first color is a bg and the list is choosing a fg color

We need to provide both - select a bg for a given fg color, and select a fg for a given bg color. Unlike WCAG 2.1, these are not mathematically the same when calculating contrast.

@LeaVerou
Copy link
Member Author

Note that while "use the range for semi-transparent colors" is scary, what you actually need is to use the min contrast. If the min contrast passes, the entire range passes.

@svgeesus svgeesus changed the title [css-color] color-contrast() should take transparency into account [css-color-6] color-contrast() should take transparency into account Jun 22, 2022
@LeaVerou LeaVerou moved this to Tuesday in 2022 New York Meeting Aug 1, 2022
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed transparency, and agreed to the following:

  • RESOLVED: When calculating color contrast between pairs of semi transparent colors, if the background is opaque, UAs should alpha blend the foreground on the background and use that as the foreground color. If the background is also semi-transparent, it would be alpha blended first with an opaque version of the foreground
  • RESOLVED: Amend previous resolution, the canvas color in previous resolution is TBD
  • RESOLVED: (rather than opaque version of foreground)
The full IRC log of that discussion <fantasai> Subtopic: transparency
<fantasai> github: https://github.com//issues/7358
<emilio> lea: current draft doesn't mention transparency
<emilio> ... most contrast arguments ignore it
<emilio> ... if fg is semi-transparent some algorithms make it work, otherwise ignore it
<emilio> ... when you have a range of contrasts there's no answer
<emilio> ... one option would be using the minimum contrast
<emilio> ... for wcag there's work to compute min/max contrast
<florian> q+
<astearns> ack florian
<emilio> ... if foreground is transparent but bg is opaque you can alphablend but in the bg case it's not so clear cut...
<lea> q+
<chris> q+ to wonder about mixed domain backgrounds
<astearns> ack dbaron
<emilio> florian: for fg there's an answer, for background... it's trickier, it's not terribly convenient to find the whole color, but if you're trying what's the best contrasting color against transparent this is not answerable
<emilio> dbaron: first intuition is that having a bg that's not opaque should be a syntax error
<emilio> ... wrt contrast ranges, maybe alpha-compositing bg with alpha over foreground with no alpha might give you the minimum contrast, but might vary per algo
<astearns> ack fantasai
<emilio> fantasai: was gonna suggest the same, composite semi-transparent bg over foreground color would give you the worst case scenario
<emilio> ... if both semi-transparent it gets extra-exciting, maybe composite against black?
<astearns> ack lea
<emilio> lea: not sure how we'd specify this so that colors are semi-transparent
<emilio> q+
<emilio> lea: compositing on black might give you the max contrast
<astearns> ack chris
<Zakim> chris, you wanted to wonder about mixed domain backgrounds
<fantasai> s/so that colors are semi-transparent/so that semi-transparent is invalid
<emilio> chris: if you have stuff like iframes that are transparent, does that allow you to find the background behind the iframe
<fantasai> i/lea: compositing/TabAtkins: in prose/
<astearns> ack em
<emilio> TabAtkins: not doing that, there's no way to know what the color will be used on
<fantasai> emilio: Making it invalid at syntax time sounds nice, but not possible in current impl
<dbaron> s/current impl/the presence of currentColor/
<fantasai> emilio: Offhand, I don't expect this to be a super common thing to hapen
<florian_irc> s/for background... it's trickier, it's not terribly convenient to find the whole color, but if you're trying what's the best contrasting color against transparent this is not answerable/For background, what authors should be supplying is not the possibly semi-transparent background color of the element, but rather the composited background against which the foreground will be seen. It's not necessarily easy for authors to figure
<florian_irc> what that is, but that's the only thing that makes sense. The color-mix function might help./
<fantasai> emilio: doing what fantasai and dbaron suggested seems a reasonable compromise to me
<astearns> ack dbaron
<lea> q+
<emilio> dbaron: what I was suggesting if they are both not opaque was to take the foreground, modify alpha to be 1, then composite the bg on top
<florian> s_what that is, but that's the only thing that makes sense. The color-mix function might help./__
<emilio> ... then compare fg composited against that
<emilio> ... that was my intuition for the worst case
<emilio> fantasai: [sanity-checks that]
<florian> s_to figure_to figure what that is, but that's the only thing that makes sense. The color-mix function might help._
<TabAtkins> composite fg over bg over (fg with alpha set to 1)
<lea> no need for color-mix(), relative color syntax can do that: lab(from foreground l a b / 1)
<emilio> dbaron: new_bg = alpha(fg, 1.0); bg = composite(bg, new_bg);
<fantasai> emilio: the goal is to make both opaque
<fantasai> emilio: so you need to composit on top of the new background that's opaque
<emilio> dbaron: this is sort of speculative, we should work it out in an issue
<emilio> astearns: well this would be the issue
<emilio> dbaron: underlying question is "does this give you the worst case?"
<emilio> lea: intuitively it seems like it might
<emilio> fantasai: so generically, we have a canvas that is the foreground with alpha 1, then we draw the background, then the foreground
<TabAtkins> fg compared against (bg on top of opaque fg)
<emilio> ... if everything is opaque then it all works out
<florian> q?
<fantasai> s/works out works out easily, otherwise you need to do some compositing/
<emilio> florian: sounds like it gives a clear answer
<emilio> TabAtkins: how can you get a less contrasting color with the foreground than the foreground itself
<astearns> ack lea
<emilio> q+
<florian> s/clear answer/, not sure it's a great answer/
<dbaron> It's probably not the absolute minimum for all algorithms, but it's probably close.
<astearns> ack emilio
<florian> q+
<fantasai> emilio: I'm not sure it'll be the least contrasting color
<fantasai> emilio: the least contrasting option would be the compositing the background with the foreground maxed out
<fantasai> TabAtkins: that's the suggestion
<fantasai> emilio: but that's not quite the same
<fantasai> emilio: the least conrasting option with the foreground is the foreground itself
<fantasai> emilio: okay, yeah
<fantasai> emilio: if you apply the background, then, yes, that should give you the worst. Nevermind
<emilio> dbaron: I'm not sure it's the least contrasting. if you state it like fantasai where you have three layers
<lea> FWIW this was the research I had done 10+ years ago on min/max WCAG contrast: https://lists.w3.org/Archives/Public/w3c-wai-ig/2012OctDec/0011.html
<lea> I can't at a glance tell if the formula for min contrast is what dbaron is proposing
<emilio> dbaron: the contrast aren't uniform with blending
<astearns> ack florian
<emilio> ... so I think there's variations where this might not work
<lea> +1 fantasai
<emilio> florian: other concern is that if we manage to find the least contrasting situation, we might fall back to black / white unnecessarily
<emilio> fantasai: I think dbaron's proposal is the best option, I propose to spec it and let people tell us why we're wrong
<fantasai> emilio: I think what I was thinking is along the lines of what dbaron thought earlier
<florian> s/unnecessarily/unnecessarily, as what's behind the semi-transparent background might not at all be that worse case scenario/
<fantasai> emilio: the worst contrast is when the blend of the color and the color below it is exactly the foreground
<fantasai> emilio: using the foreground color itself doesn't give you the worst one
<fantasai> emilio: suppose you have a red foreground, opaque red
<fantasai> emilio: and you have semitransparent white bg
<dbaron> s/of the color/of the background color/
<fantasai> emilio: can you get a way such that compositing semitransparent white will end up red?
<lea> RESOLVED: When calculating color contrast between pairs of semi transparent colors, if the background is opaque, UAs should alpha blend the foreground on the background and use that as the foreground color. If the background is also semi-transparent, it would be alpha blended first with an opaque version of the foreground
<fantasai> TabAtkins: a medium gray foreground, half-transparent black background, clearly the worst contrast is putting it over white
<fantasai> TabAtkins: putting over medium gray is not as bad
<fantasai> emilio: it's probably good enough
<fantasai> florian: could also just put white or black as the backdrop, depending on color scheme
<fantasai> emilio: [missed]
<fantasai> emilio: Gecko does have some contrast checks for selection
<fantasai> emilio: what we do in the case of semintransparent backgrounds is using the default background
<TabAtkins> Notably the worst case here is 50% transparent bg. as it gets more or less transparent, the answer becomes easier
<fantasai> emilio: basically composit with canvas, can guarantee it's opaque
<fantasai> emilio: simpler answer, maybe more correct
<fantasai> TabAtkins: how about we resolve for now that we'll adopt this approach with a color TBD
<fantasai> TabAtkins: could still use examples and thought
<fantasai> RESOLVED: Amend previous resolution, the canvas color in previous resolution is TBD
<dbaron> (rather than opaque version of foreground)
<TabAtkins> RESOLVED: (rather than opaque version of foreground)

@frivoal
Copy link
Collaborator

frivoal commented Aug 2, 2022

possible options for the canvas:

  • oppacified foreground
  • black or white on light/dark mode
  • A color picked by the UA in order to minimize the contrast (as judged by the contrast algo specified)

LeaVerou added a commit that referenced this issue Oct 21, 2022
Relates to #7358

Co-Authored-By: fantasai <725717+fantasai@users.noreply.github.com>
@LeaVerou
Copy link
Member Author

Agenda+ to resolve on color the background is composited on, which is what remains to close this (and is blocking shipping even the reduced contrast-color() that we resolved to pull into css-color-5).

@svgeesus
Copy link
Contributor

In the current draft, transparency is ignored when calculating contrast, because it was ignored in WCAG 2.1 as there were no non-opaque colors then.

Notice that APCA does specify blending the text color onto the background color using the text alpha, then computing the L ccontrast of the blended result against the (assumed fully opaque) background. Of course this is made easier because the APCA formula requires specifying which is text and which is background :)

@svgeesus
Copy link
Contributor

To me, this means that all of the color contrast functions in CSS need to explicitly say which parameter is foreground and which is background (there are various ways to do that, such as keywords or parameter order). It no longer matters that many formulae give the same result if foreground and background get swapped; none of them give the same result once foreground transparency is used to modify the effective foreground color.

@LeaVerou
Copy link
Member Author

To me, this means that all of the color contrast functions in CSS need to explicitly say which parameter is foreground and which is background (there are various ways to do that, such as keywords or parameter order). It no longer matters that many formulae give the same result if foreground and background get swapped; none of them give the same result once foreground transparency is used to modify the effective foreground color.

This is not under debate, we resolved in #7359 that the syntax needs to distinguish foreground and background, but we have not resolved on the exact syntax (and on whether there is a default).

@svgeesus
Copy link
Contributor

Another option for the default against which to composite non-opaque background would be Canvas.

@LeaVerou
Copy link
Member Author

Whatever default we pick, there will be cases where it's wrong, so it would be nice to offer a way out. How can the author select what the background is composited on? What if we add a color-over() function to do alpha compositing? Pretty sure there are other use cases for it too, and it should be relatively easy to implement.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-color-6] color-contrast() should take transparency into account.

The full IRC log of that discussion <TabAtkins> lea: We've discussed before. Right now contrast-color() ignores transparency entirely, pretends the colors are opaque.
<TabAtkins> lea: This can produce wildly wrong results.
<TabAtkins> lea: A color with a very low alpha but otherwise has a good contrast, the algo can choose that over an opaque color that would *actually* contrast better
<TabAtkins> lea: Previously we resolved that you composite a semi-transparent fg against the bg, but we didn't resolve on what to composite the bg against
<TabAtkins> lea: There are three options
<TabAtkins> lea: (1) the opaque version fo the fg
<TabAtkins> lea: (2) opaque white or balck, whichever is better
<TabAtkins> lea: (3) canvas color
<TabAtkins> lea: Or a UA-specified color.
<TabAtkins> lea: So we ahve to resolve on the color and we'll have a complete algo
<fantasai> s/Or a UA-specified color/(4) Color picked by UA to minimize the contrast (per contrast algo specified)
<TabAtkins> lea: Whatever heuristic we pick it might be wrong, so it might also be useful in a later version to add a color-over() that specifies the compositing...
<argyle> q+
<TabAtkins> TabAtkins: Weak preference for canvas color
<TabAtkins> chris: Me too, seems canvas color is a good default, takes light/dark mode into account
<TabAtkins> fantasai: Seems like it could be wronger than fg
<TabAtkins> chris: fg is gonna be the worst possible
<TabAtkins> fantasai: color could be in a subtree with a different color than canvas
<astearns> ack argyle
<TabAtkins> dbaron: I think it's posible to come up with an algorithm for "worst possible color" but not sure it's any of these
<fantasai> fantasai^: fg is not always worst possible, depends on the composited background
<TabAtkins> argyle: I'm remdined of accent color - we compute it against canvas color
<TabAtkins> argyle: I think it would be nice to have a fallback mechanism where it falls back to canvas if there's not an html or body color
<TabAtkins> argyle: So it could crawl up and try to find a solid color, otherwise use the UA canvas
<smfr> q+
<astearns> ack fantasai
<TabAtkins> fantasai: I don't think we can look for the actual bg - frequently you're rendering over an image
<TabAtkins> fantasai: and we want to do this locally without having to do layout or crawl the tree
<TabAtkins> fantasai: so i think we need an answer locally based on infromation on the element itself
<astearns> ack smfr
<TabAtkins> smfr: I think we're assumign that contrast is used on the fg of an element.
<TabAtkins> smfr: But might want to use it for the bg - seems like we're biasing
<argyle> i just used color-contrast() on the bg in this demo https://nerdy.dev/color-from-color-contrast-result
<TabAtkins> chris: We're actually not doing that - we're explicit about whether the color is a fg or bg
<TabAtkins> chris: So this is only an issue where it's the bg color that's partially transparent
<astearns> ack fantasai
<TabAtkins> fantasai: I think i'd prefer we went with opacified fg, or "UA-chosen worst possible color"
<argyle> q+
<TabAtkins> fantasai: We're trying to find a color that passes a threshold for some contrast
<astearns> ack argyle
<TabAtkins> argyle: What if we added an option for users to specify it?
<chris> color picked by the UA sounds handwavy, difficult to test, non-interoperable
<chris> q+
<TabAtkins> argyle: Like it defautls to canvas, but as an author I know what color it's gonna be against
<fantasai> chris, it's "color picked by the UA to minimize contrast per the contrast algo used"
<TabAtkins> argyle: So authors can add intelligence but we still have a reasonable default
<fantasai> which is not so vague
<astearns> ack chris
<TabAtkins> chris: I see what Adam's suggesting, but I think putting the same color in twice means you ahve to update it twice and keep in sync
<TabAtkins> argyle: Custom props is your way out of that - already this algo is loaded with inputs that need copy/paste or custom props
<TabAtkins> lea: Even using the custom prop is some repetition
<dbaron> Seems like what Adam's suggesting could also be done with a composite(A over B) color function or similar rather than additional syntax for the contrast function.
<TabAtkins> lea: Remembering which of the custom colors you're using
<TabAtkins> lea: Does seem nice as optional, but shouldn't be only way
<TabAtkins> astearns: We're over time, and I'm not hearing consensus, so let's take back to issue

@dbaron
Copy link
Member

dbaron commented Feb 8, 2023

I separated the possibility of a compositing function into #8431.


A few brief thoughts on finding the "worst case" for a transparent background: for a start, I think when we're looking for the worst case, we should be looking for the worst case under the assumption that the colors are being used in a surface that's fully opaque, uses source-over compositing and normal blend mode. Cases beyond that aren't the problem of the color contrast algorithm. An example (of the "not the contrast algorithm's problem" case):

<div style="background: black">
  <div style="background: black; color: white; mix-blend-mode: darken">
    This text is black on black!
  </div>
</div>

A very naive possibility for finding the worst case backdrop is to choose an R, G, and B component for the backdrop such that compositing the (partially transparent) background color on top of the backdrop will produce R, G, and B results that are as close as possible to the R, G, and B components of the foreground color.

I think this naive possibility does find the cases where it's possible to get to zero contrast with a particular backdrop, but probably doesn't get to minimal contrast for the cases where you can't get to zero. An example zero-contrast case is:

<div class="backdrop" style="background: rgb(155, 240, 200)">
  <div style="background: rgba(255, 140, 0, 0.4); color: rgb(195, 200, 120)">
    This text is not visible!
  </div>
</div>

Note that this case has (I think) reasonable contrast against a black backdrop (though not against white).

@Myndex
Copy link
Member

Myndex commented Feb 16, 2023

Undeclared Colors Fail

Under WCAG 2.x, it is a failure to specify a text color without also specifying a background color or vice versa: https://www.w3.org/TR/2016/NOTE-WCAG20-TECHS-20161007/F24

By definition, specifying a transparency without specifying the color that transparency exists on top of, is the same as failing to fully specify the color at all.

This does not mean that a given element must have both a foreground and background color, it only means that at some point in the cascade an unambiguous foreground and unambiguous background color can be determined (or none).

What is required, is only one of these cases:

  • No colors are the default user agent.
  • All colors are the default user agent.

As such, any compositing operations must be completed prior to calculating the colors involved in a pairwise contrast test.

This is true under WCAG2, and I would expect it to remain true under WCAG3 as it would be a mistake for it not to be. However it's easier said than done. See my next post for the deeper dive.

@Myndex
Copy link
Member

Myndex commented Feb 16, 2023

Tree Climbing for Fun and 'Posits

Obviously, compositing over images and compositing over gradients bring up additional and not-well-resolved issues.

Something to point out here, the background color is commonly specified in an element that is much higher up the DOM tree than the text or other foreground color. Most of the time to do the calculation needed for the color-contrast() function, there will be the need to trace up the DOM tree for the corresponding color(s) at the given spatial coordinates.

A background color with transparency is inherently ambiguous, as it requires tracing back not only to the previous background color, if that color is also transparent than multiple steps up the DOM tree, but also, foreground colors, gradients, effects, not to mention what happens when a transparent background of a div is straddling multiple underlying backgrounds, or the more common instance of underlying images, all may have to be considered.

Since the APCA tool was mentioned, one of the reasons it presently only offers alpha for text: It's trivial to use a text color with transparency, if the background color is fully opaque. However it is quite far out of the question to take a transparent background color as there are too many variables without known constraints or rules as to what that transparent background color might be composited over.

Without knowing that fully, a transparent background color is ambiguous at best.

In the example below, admittedly a slightly contrived case for illustration purposes, the rasterizer is providing four different background colors behind one single text color, not counting the image of course....

Click for full size
Transparent Background Examples The text below in Top Div uses a #fff9 background (sRGB, about 60% opaque or 40% transparent), and that div is itself on top of other divs with opaque color backgrounds but the divs themselves are each opacity:0.5 all on top of the main div bg image, and while unseen, the main divs bg color is #f7f which is obviously unrelated to the image. This text you're reading is #fff on a #0009 transparent background.
How should this calculate?
TOP DIV: Hello, and thank you for reading, Ill be your top div today, and todays special entree is the transparent background behind this text drizzled onto the chefs special foie gras backgrounds with more transparency, all resting on a bed of a savory ratatouille body. The big question is at what point does that make the background color as calculated here inappropriate or incorrect in terms of determining contrast? BLUE DIV: DIV WARS Episode I: The Transparent Menace ... Hey look at me! Im a transparent div with some text inside of it! RED DIV: Nice texting kid dont get cocky, you aint the only one in the galaxy thats transparent! Spatially, I texted Kessel while running a 12 parsec marathon!

Calculating contrast for each pixel is awfully expensive, but there's something more important that needs to be discussed.

Both the div called "Top Div" and the first explanatory div, have their backgrounds set at 60% opacity or 40% transparency. The BG color for the first one is black with white text, the BG color for "Top Div" is white with black text.

The readability and the apparent opacity is quite different between the two. The linear opacity is being applied to gamma¹ encoded sRGB color values while compositing.

Here is the same example except that foreground and background are reversed for the two top most divs.

Click for full size
Transparent Background Examples The text below in Top Div uses a #0009 background (sRGB, about 60% opaque or 40% transparent), and that div is itself on top of other divs with opaque color backgrounds but the divs themselves are each opacity:0.5 all on top of the main div bg image, and while unseen, the main divs bg color is #f7f which is obviously unrelated to the image. This text you're reading is #000 on a #fff9 transparent background.
How should this calculate?
TOP DIV: Hello, and thank you for reading, Ill be your top div today, and todays special entree is the transparent background behind this text drizzled onto the chefs special foie gras backgrounds with more transparency, all resting on a bed of a savory ratatouille body. The big question is at what point does that make the background color as calculated here inappropriate or incorrect in terms of determining contrast? BLUE DIV: DIV WARS Episode I: The Transparent Menace ... Hey look at me! Im a transparent div with some text inside of it! RED DIV: Nice texting kid dont get cocky, you aint the only one in the galaxy thats transparent! Spatially, I texted Kessel while running a 12 parsec marathon...

Here's an extreme close-up of the upper and lower div's text, Side by side for comparison.

Click image to zoom
60% Wbg Btxt 60% Bbg Wtxt ZOOMED

And we haven't even talked about other possible transfer modes. The point I'm getting who here is the additional ambiguity that arises from making the background color transparent, when a solid background should be the foundation that text is displayed upon.

Some thoughts

What I hoped to illustrate above more than anything else, was that doing automated color with transparent backgrounds has potentially very poor results, unless some reasonable constraints or rules are applied.

There are certainly plenty of good uses for having selectors that are set up with transparent backgrounds for elements in a design system. But the issue that comes up is the one we discussed last year, that of automated adjustment. Automated means that no human is looking at it to evaluate or make the adjustment. As such:

  • Background colors need to be composited before a contrast value can be calculated.
  • Transparency as currently defined/calculated per CSS is linear, not perceptually uniform, and is applied to gamma encoded colors (not linear), such that a given opacity value does not provide perceptually consistent results.
    • this is particularly of concern when switching from light mode to dark mode. Transparency which works for a pair of colors in light mode very likely will not work the same way when reversed for dark mode.
  • For any automated control, and the color-contrast() function is an automated color control, it can be difficult to determine what a background color is going to be if it has any transparency.
    • sampling every pixel is computationally wasteful unless done at the rasterizing stage, which means that determining contrast would have to be deferred until then, which IMO is not a viable option.
    • even then, what would be done if there were multiple contrasts within a div that text was on? Or it's on an image? Such busy backgrounds should not be used with text, as I describe here with examples.
    • compositing over an image isn't bad per se, but in practice frequently is bad, and frequently does create poor results.

Key takeaway

If a human designer is evaluating, that's one thing—but for an automated tool that deals with color appearance, then a means must be provided to replace the eyes of a human designer with that of a standard observer.

If that's not directly possible or practical, then appropriate rules must be in place to constrain the use of transparent backgrounds.

Example of a reasonable rule set:

  1. The background color underlying a transparent background must not itself be transparent.
  2. The element containing the transparent background must be fully enclosed by the element which has the fully opaque background.
  3. When used over an average image, and text is black, then BG:
    • #ffffff opacity must be greater than 0.7
    • #a0a0a0 opacity must be greater than 0.9
    • in-between values interpolated
  4. When used over an average image, and text is white, then BG:
    • #000000 opacity must be greater than 0.5
    • #909090 opacity must be greater than 0.8
    • in-between values interpolated

Disclaimer: these opacity values have not been thoroughly evaluated, and should not be considered normative, only here as an example for this discussion.

TL;DR

Transparent backgrounds present a lot of problems for any automated color adjustment control. The potential for misuse and abuse is great. If the use of transparent backgrounds is to be permitted in conjunction with automation, reasonable constraints need to be in place.

Thank you for reading

Andy


TANGENTIAL FOOTNOTE: ¹

1
Re "gamma" — yes I'm quite well aware that sRGB technically uses a piecewise tone response curve for encoding, not a simple gamma. Nevertheless gamma as an "all inclusive meaningful term" is the simple, industry standard convention for discussion purposes, at least here on the West Coast, and Hollywood in particular. Between saying "piecewise tone response curve" and "gamma", which one is easier to say/work with? Particularly when everyone in the industry knows that's what's meant.

And it's useful to point out, the IEC sRGB spec specifies the EOTF as "a simple 2.2 exponent", and the piecewise is only there for mathematical convenience and intended to be as close as possible to the simple 2.2 exponent. The piecewise does have added benefits for encoding when the display is using a simple exponent EOTF. The piecewise should preferably be used for decoding for image processing purposes to prevent round-trip problems. But image processing needs are not the same as sending something to a display or emulating the characteristics of a display.

Copypasta from that document: (emphasis added)
...This standard dramatically improves the colour fidelity in the desktop environment...the input and output device vendors...easily and confidently communicate colour without further colour management overhead in the most common situations. The three major factors of this RGB space are the colorimetric RGB definition, the simple exponent value of 2.2, and the well-defined viewing conditions, along with a number of secondary details necessary to enable the clear and unambiguous communication of colour...

It's nevertheless true that the IEC made some non-normative, opinion comments in the appendix, regarding the use of the term "gamma", but that appendix aside, use of the term continues in general discussions in industry for reasons already outlined.

This related thread at ACEScentral is quite interesting, and includes comments by Jack Holm.

@LeaVerou
Copy link
Member Author

@Myndex not sure what you are proposing. <color> values in CSS can have transparency. contrast-color() accepts <color> values, therefore it needs to do something reasonable with transparency. Feel free to do all the advocacy you want that people shouldn't do that, the function still needs to return something reasonable.

@Sora2455
Copy link

Maybe just have the function fail (and the line ignored) if any of the parameters are transparent? That way a basic version can be released, with the difficult questions about transparency can be answered later - and at that point references using transparency would start working as per progressive enhancement.

@tabatkins
Copy link
Member

We can't ignore the line, since the exact color being operated on might not be known until used-value time, far after parsing and cascading. So at that point we're stuck with the property value we've got and have to get some color out of the function.

@Myndex
Copy link
Member

Myndex commented Feb 18, 2023

not sure what you are proposing.

Hi Lea @LeaVerou

Click to view side comment Yes, it's been brought to my attention that I'm not generally well understood here. My prolixity has the better of me, I suppose I should attend law school....

I was not proposing anything specific per se, just opening the conversation into something important, at least in terms of accessibility.

Undefined color is a fail in WCAG 2

It also fails APCA-RG¹ and I should expect that it will fail the future WCAG_3.

...it needs to do something reasonable with transparency...

I agree, and that was the point of my post. It needs to do something reasonable. To me, reasonable means that a there are constraints that prevent certain edge cases, and also prevent common cases that result in ambiguous or undefined colors.

So this means error handling.

To me, an error should default in the direction of accessibility, itch probably means that in the case of an error, that it spits out a solid, opaque color as the fallback for the given text. Nevertheless we have to recognize that this could create its own separate accessibility issue if it covers an element that is needed for interaction for instance.

A tangent to this thread discussing legal issues

Click to view tangent legal discussion, with cites and references

The remainder of this post maybe tangential to this specific thread but generally does relate to an issue I've seen in several threads for the color-contrast() function.

...Feel free to do all the advocacy you want...

OK, in that case.... I was going to put this in a different thread, but as I'm not sure which thread would be most appropriate, I'll just make it this one. Here we go:

Legally, Eagles see very well

And people don't. Median vision internationally is 20/40.

Part of the genesis of my post above is the legal issue, because I'm seeing in some of the IRC logs, a general sentiment of "you need WCAG2 because it's 'legal' and APCA is 'not'", which echos rumblings of that rumor-campaign asserted by a small-cult-of-trolls which I try to ignore as much as possible.

So I'll just briefly mention that APCA is stricter than WCAG 2 in terms of "actual accessibility", and as far as the very few colors that are not backwards compatible because APCA passes a few that WCAG2 fails, WCAG2's false fails are harmful to accessibility for people with color vision deficiency3,8.

Also, here's the TL;DR: if people are worried about which algorithm is in there for "legal reasons", then they ought to be worried about how an ambiguous color due to a transparent background is going to affect the legality of their site as well. Because in this later case, it could actually make a site functionally inaccessible, and functional inaccessibility is the bright-line that lawsuits are based on.

Actual accessibility is what is legal

In almost² all contexts and almost² all jurisdictions, actual accessibility is the stated goal more-so than arbitrary values. And this is definitely true in the United States where the majority of rules/regs relate to ADA compliance, not WCAG2 (except in some narrow areas).

I'm not even going to get into the fact that WCAG 2 contrast is not empirically tested, was objected to by stakeholders back in 2007 including IBM, and also was never subject to any formal peer-review. WCAG 2 cites cherry-picked obsolete³ standards that referred to obsolete technology⁴, and further review⁵ of the documents ⁶ and underlying⁷ basis for justifications⁸ leading to unintended consequences⁹, are less than one would hope for a "standard" shoved into "law"... Nevertheless the few narrow regulatory areas it is in typically have exceptions.

As an example, the US Access Board 508 regulation defines the use of WCAG 2.0 (not 2.1) A and AA, but 508 just applies to US government related agencies, and also has two additional, substantial exceptions:

1) Does not have to conform if there is no commercially viable alternative that does conform.

2) WCAG_2 methods do not have to be used if alternate methods are used that meet or improve the goals of accessibility.


Again I'm going to make the following statement: APCA is stricter than WCAG 2 ref 3 in the ways and use cases that are important for readability. Quite literally, the places where APCA might pass a color pair where WCAG 2 would incorrectly reject (which is the only reason it's not backwards compatible) happen to be in those areas where WCAG 2 creates conditions that are harmful to readability, especially for people with color vision deficiency (primarily protanopia, WCAG 2 create a condition where it rejects colors that would be good for protanopia and passes related colors that are very bad for protanopia).8

And if somebody is really concerned about also "hitting the arbitrary numbers", but they want actual accessibility they can use BridgePCA which artificially rejects colors (that are potentially usable) to maintain backward compatibility.


WCAG the Dog

Most nations with a regulation where WCAG2 is mentioned/defined, apply mainly or solely to that government's own sites. In Australia they extended it to more, but only for 2.0 level A, and level A doesn't even cover contrast.

Federally in the United States, the ADA not specify WCAG_2. It only specifies "must be accessible"¹⁰. But that linked article points out the absurd weakness of the ADA's regulations for visual contrast. This recent 2017 article was written, by the way, by Dr. Arditi, who did some work on WCAG_2 though was taken out of context⁶ back in 2004/7 and mangled a bit into what became WCAG2 1.4.3.

Click to enlarge this (pathetic) sample of an ADA compliant sign (from Dr. Arditi's article⁶)
an example of a sign that passes ADA yet is pretty much unreadable for many people because it lacks contrast

As I think you can recognize in this image, even ADA compliance is an incredibly low bar. APCA stomps all over that.

There was once a Federal lawsuit (Wynn-Dixie) that mentioned WCAG2, however it was vacated by the 11th Circuit Court of Appeals, and is moot. Nevertheless there is a more public regulation in the US, the FAA requires at least 25% of airport kiosks to comply with WCAG_2. (US airports and airspace is federally regulated.)

Automated failures

The recent automated testing by WebAim showed that of a million websites, 86% fail WCAG 2 contrast in automated testing. But there are not 860,000 lawsuits about it. I discussed some of the pitfalls of automated testing11, and the importance of actual accessibility.

Sure, there have been lawsuits regarding accessibility, most in California and New York, as those states have strong laws (i.e. profitable for attorneys) relating to accessibility, but as far as California, they rest on ADA (not WCAG 2). California AB434 does mandate WCAG 2, but only for state government agencies/entities.

The lawsuits that I have reviewed that have been brought (like Dominoes) have been about functionally inaccessible junk, and cite the ADA. Nevertheless this is certainly a changing environment, and one to be aware of.

TL;DR

If I was a site owner, I would be concerned about being actually accessible as the proactive way to prevent a lawsuit.


Disclaimer and notes

Despite writing a column on constitutional law some decades ago, I am not an attorney and nothing listed in this post should be construed as legal advice. Your mileage may vary, void where prohibited, caveat emptor, opinions are stated as persona pro se.

As a sidenote, I love the law

And had I not lost my eyesight when I did, I might be an attorney now, as circa 2012 I was planning (or at least considering) law school12, reading LSAT practice tests, and about to take the LSAT to see how much of a scholarship I would qualify for, when I found that I couldn't read the small legal-print in page-footnotes—my journey into low vision started at that point with the rapid-onset cataracts taking hold.

So there's that.

Since that brings up the subject, if I don't repeat this advice often enough, to anyone reading, always wear UV protective eyewear, take frequent breaks from the computer, and use natural tears eyedrops, I happen to like Systane myself.

And never use steroidal nasal inhalers, no matter how bad your allergies might be. Tell your doctor no. I could make that into a slogan: "Carry Kleenex instead or go blind"... 😳

Thank you for reading.

Footnotes

  • Note¹ APCA-RG is APCA Readability Guidelines, which are developing independently, with a different scope, and separate from WCAG 3.
  • Note² And I say "almost" because it's impossible for me to know the minutia of the laws in all the countries of the world, though I have spent time looking. It is up to everyone to know the laws of their land as they apply to them.
  • Notes    3   4   5   6   7   8   9   11 are self-referential links to gists, articles, or posts written by the author of this post, which nevertheless may have additional references or links to other sources.
  • Note 10 is Dr. Arditi's article.
  • Note12 With my health improving so far this year I'm once again considering a law degree... if I start in the fall, I could pass the bar at age 62... Then I can spend the rest of my life suing the crap out of the pharmaceutical companies that made the steroidal nasal inhalers that I was once prescribed that are almost certainly the reason I developed early-onset cataracts. ... Never give up!
  • Bonus note: and yes, the oblique, self-deprecating comment regarding prolixity and law school at the beginning of this post was specifically to provide the foundation for these little Easter eggs at the very end. Congrats on making it all the way through today's post.

@Sora2455
Copy link

Okay then, maybe if color-contrast() is passed a colour that isn't fully opaque, it treats it as though it is and prints a warning to the dev console (an error maybe even)?

@LeaVerou
Copy link
Member Author

LeaVerou commented Feb 18, 2023

@Myndex This is a general comment, but also applies to many of your replies here: it is not constructive to these conversations to flood them with super long comments that are pages and pages of musings. This is not the right venue for elaborate colorful prose. Please spend the time to shorten your arguments to what is actionable and relevant to the topic at hand. If you are so inclined, you can put additional background information in <details> or link to it, so that those without the time to dive in (likely the majority of us) can just read what that is immediately relevant, and discussion can continue.

I understand that when you really care about a topic, and have spent a considerable amount of your time studying it, it is often tempting to write lengthy messages dumping all of the info on other people and/or having some fun with what you're writing. In my experience, it actually has the opposite effect. Either it halts the conversation, because people cannot invest that kind of time, or it gets ignored, or it gets skimmed with readers picking up bits here and there. It's much better to condense it yourself, since you know which bits are important much better than others skimming. As for the colorful prose, there's a time and a place, and technical discussions in a WG is not it.

For example, if I'm readingskimming your message above correctly, it could have been condensed to:

Laws do not actually mandate WCAG 2.1 or any other specific specification. They instead mandate actual accessibility, and APCA is strictly superior in that. [source]

The source could even be one of your articles, including all of the above, but this thread is not the place for posting full-blown articles.

@Myndex
Copy link
Member

Myndex commented Feb 19, 2023

@LeaVerou

Thank you for your feedback, if you haven't noticed I actually am using the details/summary tags more often lately in many of my messages,

Click to expand ....having recently found that they worked here on Github (many formatting-type tags I've tried are stripped here). In fact I used it in the message previous to hide some tangential minutia.

The use of this is similar to that of reducing the message, what is the important essence and what can be discarded?

It is not always clear where that balance lies.


Though in the message above, I originally indicated the tangent-break with a header instead.

Based on your commentary I have edited that message to insert the detail/summary tags as you suggest, I hope it meets with your approval.

Click to view additional colorful prose

Nevertheless, in terms of sticking to the point or not, in the post previous to the one for which I am being currently criticized, the door was opened with the following comment:

...Feel free to do all the advocacy you want...

To which I responded with:

OK, in that case....

And did nevertheless provide an opportunity to simply exit the post at that point, without reading further by specifically indicating that the remainder of the post was tangential.

I am aware that I have a difficulty determining when where and how to structure deeper information dissemination versus succinct, short, statements. A perceived problem is that short statements by definition are missing foundation, and there's the appearance of a lack of foundation in general, where foundation is often needed for complete understanding.

Directed at no one in particular.

While I appreciate that some people, and I have particularly noticed millennial and GenZ culture, prefer things reduced to "meme length". I suppose that myself as a GenX/Boomer (cusp) my point of view on disseminating information may be a little bit different—I come from a generation literally raised on reading actual books cover to cover—and then the Internet effectively destroyed the print industry, some studies have indicated¹ that reading has decreased by 40% over the last 20 years.

And perhaps this means that I need to bend with the times and develop new communication skills that are more succinct.

I do recognize that one of my communication deficits is dwelling on the minutia, which is a well-known trait of neurodivergent individuals on the autism spectrum. (I am on the spectrum, as you may be aware, diagnosed an Asperger's savant.) As a result, and with awareness of my proclivities, I do try to mitigate burdensome prolixity.

Part of the understanding of the nature and extent of my communication deficits regarding this issue comes from a recent study in 2020, which investigated the nature of peer-to-peer communication between autistic and allistic groups.

From the abstract of "Autistic peer-to-peer information transfer is highly effective"²

Effective information transfer requires social communication skills. As autism is clinically defined by social communication deficits, it may be expected that information transfer between autistic people would be particularly deficient. However, the Double Empathy theory would suggest that communication difficulties arise from a mismatch in neurotype; and thus information transfer between autistic people may be more successful than information transfer between an autistic and a non-autistic person.

Indeed, the study found that the autistic group performed better than the allistic group, while the mixed group not only performed poorly, animosity developed.

Subsequently, and in an effort to improve my communication in general, and relieve the animosity that apparently I am told I create, I have been experimenting with different ways to organize messages to allow neurotypicals to skim through them and still absorb the important gist, whilst foregoing the minutia. For example in the message that was commented on above, I originally indicated the point of the tangent-departure with a simple heading, thinking this would be enough to allow someone to skip the remainder of the message, after reading the first few paragraphs. Apparently this was not sufficient.

I have also made attempts to make longer posts more readable by making them more entertaining, using the aforementioned "colorful prose"—but according to the comment above that also is not appropriate. My bad.

I nevertheless find it challenging to distill the essence of an issue without also laying the foundation. And I do believe that lack of foundation permeates communication today, with substantial negative effect.

As an observation, I encounter younger individuals who seem to feel that after reading a seven-word meme and extrapolating the remaining information out of thin air, they suddenly consider themselves subject matter experts, ironically exuding an entitled attitude of academic ableism. I have little to no tolerance for that. As far as musings, I'm musing as to how much of this cultural incongruity is the tragic result of that George W. Bush educational program known as "No Child Left With A Brain".

Though alternately, and thinking critically about this, there is perhaps a more likely scenario: a greater problem might be that the Internet, for all that it enables, also has provided a socially devastating signal-to-noise ratio. Easy access to garbage-on-demand is still garbage, and further allows entities with questionable motivations to manipulate the gestalt by "planting seeds of misinformation", or worse.

According to Pew Research, polarization of American political opinion is at all time highs, a trend that began circa 2006, coincident with the birth of social media. Some years ago I posited that the polarization was due to our election methods ³, but ultimately it seems to be of darker origin.

I don't mean to say that the blame rests with social media per se, but social media has provided the conduit for discord campaigns ⁴ of foreign state actors to directly influence public opinion in a manner intended to divide and create social chaos. The flat earth nonsense is one example, but so is the deep political divide that has grown.

How best to combat this? Because LOL Cats and seven word memes are not going to save the day here.

A Musing Summation

The points here are that:

  1. There is substantial misinformation on the internet, including here on GitHub in W3 forums.

  2. Short, micro-aggressive statements still can have a negative effect, particularly when from authority, which makes it even more important that they be challenged with supportable and referenceable statements.

  3. Providing support and foundation for statements requires a certain amount of disclosure which may result in more "words in a post", and longer, supported responses certainly might be objected to by holders of opposing views; such is the nature of academic conflict or dispute.

  4. This message is an example of an unrelated musing, but my previous message was nevertheless on point. While my earlier message itself conceded that it may have been tangential to this thread, it is addressing a large misunderstanding specifically related to color-contrast() and contrast algorithms, and concerns a misunderstanding that I see being repeated, and therefore should be addressed with foundational information.

References

¹"International Reading Crisis" link in "Contrast of Errors"
²"Autistic peer-to-peer information transfer is highly effective"
³"Ending Polarized Politics: Two Parties, Many Problems"
Senate Intelligence Committee Press Release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. css-color-6
Projects
Status: Tuesday
Development

No branches or pull requests