Closed josepharhar closed 3 years ago
First, props for correctly undoing gamma-encoding when calculating relative luminance (many get this wrong).
In terms of the crossover point, it may be helpful to know that lab(50% 0 0)
is color(xyz 0.177596 0.184187 0.151993)
in other words a CIE Lightness of 50% (visually mid way between white and black) is a luminance (Y) of 0.184.
I know we discussed this earlier, but I think it'd be best if we force the author to give two colors instead of trying to magically do stuff.
We do something similar with the OS accent color in Gecko for the new form controls, using the relative luminance to compute lighter / darker colors from the OS accent: https://searchfox.org/mozilla-central/rev/74d0efd1107a26f178b108b6a18a179e9b06547c/widget/nsNativeBasicTheme.cpp#136-165
However we do have a known good pair of foreground / background colors provided by the OS, which ensure that we don't mess up contrast.
there's conflict with auto choosing a background with color-scheme too. like, i can specify a dark color scheme preference, get dark controls, then pick an accent color which turns all the controls light.. which feels like i'm in the middle of a game of wack-a-mole.
there's also color-contrast()
in Color 5 that seems handy here, for Joey and developers?
maybe a simpler route is better here? less magic like @emilio is saying. could spend all this time trying to write algo's which keep form controls within proper contrast, then developers make all labels and paragraphs white on white with color and background css. I understand the original intent here, to force prevent low contrast controls, but maybe it's over-reaching? i dont think it's intuitive to tell someone: "you can use your brand color as form control accent colors now! but, beware, the color you choose may flip the controls to a light or dark theme." seems obvious i have a new responsibility once i start styling form controls different then their defaults?
🙂
I know we discussed this earlier, but I think it'd be best if we force the author to give two colors instead of trying to magically do stuff.
There can be more than two colors used in the control, tho, so this still wouldn't solve everything; magic will always be required unless we explicitly specify what set of colors are allowed to be used on controls.
Should any of this behavior be specified? Should there be any guidance on how to color the rest of the form control in response to the accent-color?
Happy to provide more non-normative guidance, so engineers don't have to reinvent the wheel here on their own. Basing it on relative luminance sounds completely reasonable, tho I'd want to do some testing to see how it responds in practice. I'll see if I can get Canary working again on this machine to try out your impl. ^_^
There can be more than two colors used in the control, tho, so this still wouldn't solve everything; magic will always be required unless we explicitly specify what set of colors are allowed to be used on controls.
True, but there's usually a need to have some sort of background and foreground color. The rest of the colors are mostly decorative. Asking the author for two colors ensures there can be contrast when the engine deems it necessary.
We've got https://github.com/w3c/csswg-drafts/issues/5544 open on providing multiple alternative accent colors to be chosen by optimizing contrast. But I don't think we need to force the author to give more than one.
Agree with Tab that we can add non-normative suggestions e.g. on what math to use to calculate or adjust contrast, but I would be against adding any kind of normative rules: this is an area where UAs should be allowed to freely experiment.
@emilio wrote
We do something similar with the OS accent color in Gecko for the new form controls, using the relative luminance to compute lighter / darker color
I would be interested to know about these magic numbers
constexpr float kLightLuminanceScale = 25.048f / 13.693f;
constexpr float kDarkLuminanceScale = 9.338f / 13.693f;
constexpr float kDarkerLuminanceScale = 5.901f / 13.693f;
I would be interested to know about these magic numbers
What I currently have implemented in chrome is a check to see if the relative luminance is less than 0.5, which is sort of a magic number that I imagine will be adjusted unless we decide to do something really different here. There is some similar chrome UI code which has a separate magic number. I don't know how it was selected, and I could see myself reusing it...
@josepharhar thanks for the pointer.
A relative luminance of 0.5 is no-where near the middle of the lightness scale, though, if that is what you were looking for. (A CIE Lightness of 50% is in the middle).
lab(50% 0 0)
is color(xyz 0.1776 0.18419 0.15199)
is rgb(46.637% 46.633% 46.627%)
so the relative luminance (the Y component) is 0.18419
lab(76.07% 0 0)
is color(xyz 0.48212 0.50001 0.41261)
is rgb(73.542% 73.536% 73.528%)
so much lighter; here the relative luminance is 0.5
I can get close to that other magic number, lab(53.135% 0 0)
is color(xyz 0.20412 0.2117 0.1747)
so reative luminance 0.2117.
I don't understand the comment about kGoogleGrey900, either
But is is certainly a better threshold than a relative luminance of 0.5.
maybe a simpler route is better here? less magic like @emilio is saying. could spend all this time trying to write algo's which keep form controls within proper contrast, then developers make all labels and paragraphs white on white with color and background css. I understand the original intent here, to force prevent low contrast controls, but maybe it's over-reaching? i dont think it's intuitive to tell someone: "you can use your brand color as form control accent colors now! but, beware, the color you choose may flip the controls to a light or dark theme." seems obvious i have a new responsibility once i start styling form controls different then their defaults?
Perhaps would it make sense to instead of having the browser decide to color the rest of the control dark or light, let the page specify color-scheme:dark or color-scheme:light? And then we add a DevTools console message or add something to the DevTools styles sidebar to say when the combination of color-scheme and accent-color doesn't have enough contrast?
Maybe that's not how color-scheme should be used since it can just be changed dynamically by the OS...
I would be interested to know about these magic numbers
They're not magic. We have a "canonical" color scheme (a few lines above), the one you get on Windows or with widget.non-native-theme.use-theme-accent=false
.
Those numbers are just the luminance of the light / dark / darker colors in the canonical color scheme (25.04791, 9.33808, and 5.90106% respectively) divided by the luminance of the regular accent color (13.693%). So we scale the luminance of the accent color by similar amounts to achieve similar looks with different accent colors. We use a similar trick to auto-darken scrollbars too.
So I did a prototype of this on Firefox and it suffers from the same issue, depending on whether you consider the color "dark", I choose a white or black foreground color, and that just creates very weird contrast in some colors which aren't too dark nor too light, and the choice of white or black seems pretty arbitrary.
So I'm pretty sure that it'd be better if we allowed authors to provide a "foreground" color of sorts. I also think that we don't want to auto-switch to dark-mode form controls, which is different from that IMO.
I just re-read the spec, and I noticed this part:
The UA must maintain contrast for legibility of the control, and in order to do so may adjust the luminance or brightness of the color or make color substitutions in other parts of the control (e.g. switching an overlaid glyph from using color to using background-color). It may also generate variations of the color for gradients etc. to match the control to platform conventions for the use of the accent color.
This seems to suggest that not only the colors used in other parts of the control can be changed, but also the accent-color itself...?
Also, I made a gif that better demonstrates what I currently implemented in chrome (I haven't tweaked anything since starting this discussion):
I recently updated the behavior in chrome to determine when the color-scheme gets flipped to look at the contrast ratio of the adjacent color used when painting each control. However, in the interest of interop, maybe it would be better if we decided on something else...
We've got #5544 open on providing multiple alternative accent colors to be chosen by optimizing contrast. But I don't think we need to force the author to give more than one.
I skimmed the issue and it's a bit mind boggling for me to figure it all out, but since we aren't forcing the author to give more than one, I'm going to focus on making this work with the single option case.
So I'm pretty sure that it'd be better if we allowed authors to provide a "foreground" color of sorts. I also think that we don't want to auto-switch to dark-mode form controls, which is different from that IMO.
@tabatkins and @fantasai seem to be against providing multiple colors for foreground and background based on their previous comments in this thread...?
Happy to provide more non-normative guidance, so engineers don't have to reinvent the wheel here on their own. Basing it on relative luminance sounds completely reasonable, tho I'd want to do some testing to see how it responds in practice.
Agree with Tab that we can add non-normative suggestions e.g. on what math to use to calculate or adjust contrast, but I would be against adding any kind of normative rules: this is an area where UAs should be allowed to freely experiment.
@tabatkins @fantasai could I get some suggestions on what to do with the rest of the control in response to the accent-color? Do you think that flipping the color-scheme is a good idea or a bad idea? Are there any alternatives? Is my current contrast ratio check of 3 too aggressive? Should I change it back to a luminance check?
i dont think it's intuitive to tell someone: "you can use your brand color as form control accent colors now! but, beware, the color you choose may flip the controls to a light or dark theme." seems obvious i have a new responsibility once i start styling form controls different then their defaults?
Another way I could see this playing out is where authors (must?) write two accent-color rules based on the color scheme like this:
@media (prefers-color-scheme: dark) {
input {
accent-color: lightblue;
}
}
@media (prefers-color-scheme: light) {
input {
accent-color: darkblue;
}
}
Responding to @emilio's comments from my intent to ship:
So the way form controls are drawn on Firefox requires two colors, a "background" color (the accent color), and a "foreground" color (a color that has sufficient contrast with the accent color). All other decorative colors are derived from the accent color, by tweaking the luminance.
For native form controls, the foreground and background colors are provided by the OS (the macOS accent color, the Linux theme accent color, etc). On Windows and Android it's hard-coded to white-on-blue, though you can use the OS accent color if you change
widget.non-native-theme.use-theme-accent
to true).For the accent-color property, as specified it only requires one color (the accent color), so we just choose a white or black foreground depending on whether the color is "dark enough":
Note that we always blend the accent color with white to make sure it's opaque.
Anyhow, I think the current approach is not great, but is as good as it can get with only one color. I think it's slightly unfortunate as some accent colors would still look better with white, and the authors could want e.g., a checkmark that isn't white or black. That's why I think the option of providing two colors (background and foreground) to the property is best.
I see why specifying a foreground and background color makes sense for firefox, but in chromium we have a bunch of hard coded light scheme colors and dark scheme colors. I presume that all of these were hand picked by UX people as opposed to being generated based on relative luminance... I suppose if the relative luminance foreground/background thing is something we should be doing instead when accent-color is present, then we could back-calculate the relative luminance of these dozens of colors to try to make something that resembles firefox, but it sounds rather complicated and I wonder if it would end up better than my current forced-color-scheme-when-needed implementation.
I made a test page with many checkbox accent-colors and compared the output with firefox nightly, chrome before my new contrast ratio patch, and chrome after my contrast ratio patch:
With the idea in mind of removing the harsh transition between light and dark themes, I decided to try generating the checkmark color based on whatever grayscale color has exactly the desired contrast ratio, and I ended up with these. This is not the current behavior in chromium like my last comment, this was just an experiment. I feel like they simply suggest that we should be using a black checkmark in most cases though...
@tabatkins and @fantasai seem to be against providing multiple colors for foreground and background based on their previous comments in this thread...?
I am, yes. I think if you want more information than just accent-color
, some combination of color
and color-scheme
and maybe also background-color
(of either the element or the canvas) should give enough information to do something that coordinates with the page. The use of colors varies a lot in form controls (across controls, across platforms, and across time), checkboxes being one of the simplest and most consistent. We know we're not going to be able to ask the author for a full, exact palette for every control, so we need to accept that the author can only give us hints rather than instructions here.
There's some cases where contrast will require a light color or a dark color, but in the middle zone there's a lot of leeway. Which way to bias might want to take into consideration the color-scheme
(as you've done in the updated Chrome patch) but also things like “is the checkmark in our design system intended to coordinate with the background color or the foreground color of the theme” which is going to vary based on UA- and platform-specific design choices. So we can't dictate that in the spec.
The only thing we're going to dictate, is that the UA does its best to ensure some reasonable level of legibility. (It doesn't have to maximize contrast.)
As for pages that use tinted foregrounds/background colors, you can check color
and/or background-color
to see if either creates enough contrast to use in place of the system default colors. A page with dark brown text, a tan background, and light green accent-color for example, might want dark brown or tan checkmarks instead of black or white ones.
Remember the point of accent-color
isn't to give 100% control over the checkboxes to the author. It's to let them influence the colors of the form control scheme designed by the UA. In other words, its parameterizing the design logic that led to the default colors, not dictating the final colors.
I propose that we leave the spec as-is and close this issue.
Relative to when I opened this issue, I now have an implementation that I am confident in and I believe makes sense. In the scheme of things, I think that the firefox implementation is pretty similar to chrome's since we are both flipping the color of the checkmark between light and dark. If firefox wishes to improve compat by unifying the breaking point where we flip the color of the checkmark, I am happy to discuss and possibly adjust the point at which we flip the checkmark in chrome, even after shipping. I don't feel confident that we can go back and change the spec to allow multiple colors due to the arguments provided in this thread.
Based on the lack of recent feedback, and the canceling of today's CSSWG meeting, I'm going to close this issue as per my last comment.
I still think we should have some discussion about this (even if it's on next week's meeting or something).
Note that what Gecko does and Blink does isn't just having different contrast thresholds (that is true for checkboxes, but not for a bunch of other form controls which do change to dark backgrounds in Blink but not in Gecko).
I'd still much rather have the author control this than inventing magic thresholds tbh. I'm happy to concede but I'd rather have at least a resolution on this.
Thanks for the response! I'm happy to discuss this in the weekly meeting.
Note that what Gecko does and Blink does isn't just having different contrast thresholds (that is true for checkboxes, but not for a bunch of other form controls which do change to dark backgrounds in Blink but not in Gecko).
I see, I added another test to https://accent-color.glitch.me and like you said, <input type=range>
and <progress>
don't respond to low contrast from accent-color in firefox. Is there anything you'd like to see happen here...?
The CSS Working Group just discussed accent-color background colors and contrast
, and agreed to the following:
RESOLVED: Close issue, one color accent-color for now
Closing as per meeting resolution
accent-color allows the page to specify a color to be drawn sort of in the foreground of several form controls, but does not specify anything about what color the browser should draw the rest of the form control with.
When I was implementing this in chromium, I realized that I needed to draw the rest of the background of the form control in a color that had enough contrast to the accent-color in order to make it easy to see the accent-colored parts. I made a basic solution to this in chromium by looking at the "relative luminance" of the accent-color and using that to decide if the accent-color was light or dark, and then drawing the rest of the control as if it were in color-scheme:light or color-scheme:dark based on that.
Should any of this behavior be specified? Should there be any guidance on how to color the rest of the form control in response to the accent-color? Does anyone have any feelings about the current implementation which you can try out in chrome canary, such as tweaking the point where it switches from light to dark or finding some way to make it have a range of background colors instead of just two?
Some more context here: https://bugs.chromium.org/p/chromium/issues/detail?id=1189332 Example site for testing: https://css-accent-color.glitch.me/
cc @mfreed7 @fantasai @argyleink