Bug 1722031 - Tweak accent-color foreground computation and let it ride the trains. r=mstange

The accent-color computation right now chooses between black and white,
which is not ideal.

I tried to make it so that authors could choose the foreground colors in
the linked CSSWG issue from the comment, but that didn't go anywhere.

I think choosing a contrasting color that is in-line and contrasting
enough with the accent-color chosen by the page when darkening is better
than just black or white.

If we want the black-or-white behavior we can just change
layout.css.accent-color.target-contrast-ratio to something large enough.

https://accent-color.glitch.me/ is a nice playground to see this patch
in action.

Differential Revision: https://phabricator.services.mozilla.com/D120723
This commit is contained in:
Emilio Cobos Álvarez 2021-07-24 13:30:25 +00:00
parent 01317e823b
commit 9f65d4a846
2 changed files with 57 additions and 7 deletions

View File

@ -6808,10 +6808,31 @@
# Whether the `accent-color` css property is enabled.
- name: layout.css.accent-color.enabled
type: RelaxedAtomicBool
value: @IS_NIGHTLY_BUILD@
value: true
mirror: always
rust: true
# The minimum contrast ratio between the accent color foreground and background
# colors.
#
# We don't use this for text, so we need a contrast of at least AA (for user
# interface components and graphical objects), which per WCAG is 3:1
- name: layout.css.accent-color.min-contrast-ratio
type: float
value: 3.0
mirror: always
# The target contrast ratio between the accent color foreground and background
# colors when darkening.
#
# We aim a bit further than the minimum contrast ratio, which seems to provide
# nice results in practice.
- name: layout.css.accent-color.darkening-target-contrast-ratio
type: float
value: 6.0
mirror: always
# Whether the `aspect-ratio` in css-sizing-4 is enabled.
- name: layout.css.aspect-ratio.enabled
type: bool

View File

@ -160,6 +160,40 @@ ColorPalette::ColorPalette(nscolor aAccent, nscolor aForeground) {
mAccentDarker = sRGBColor::FromABGR(GetDarker(aAccent));
}
static nscolor ComputeCustomAccentForeground(nscolor aColor) {
// Contrast ratio is defined in
// https://www.w3.org/TR/WCAG20/#contrast-ratiodef as:
//
// (L1 + 0.05) / (L2 + 0.05)
//
// Where L1 is the lighter color, and L2 is the darker one. So we determine
// whether we're dark or light and resolve the equation for the target ratio.
//
// So when lightening:
//
// L1 = k * (L2 + 0.05) - 0.05
//
// And when darkening:
//
// L2 = (L1 + 0.05) / k - 0.05
//
const float luminance = RelativeLuminanceUtils::Compute(aColor);
// We generally prefer white unless we can't because the color is really light
// and we can't provide reasonable contrast.
const float ratioWithWhite = 1.05f / (luminance + 0.05f);
const bool canBeWhite =
ratioWithWhite >=
StaticPrefs::layout_css_accent_color_min_contrast_ratio();
if (canBeWhite) {
return NS_RGB(0xff, 0xff, 0xff);
}
const float targetRatio =
StaticPrefs::layout_css_accent_color_darkening_target_contrast_ratio();
const float targetLuminance = (luminance + 0.05f) / targetRatio - 0.05f;
return RelativeLuminanceUtils::Adjust(aColor, targetLuminance);
}
} // namespace
class nsNativeBasicTheme::AccentColor {
@ -189,12 +223,7 @@ class nsNativeBasicTheme::AccentColor {
if (!mAccentColor) {
return sDefaultPalette.mForeground;
}
// TODO(emilio): Maybe sColorBlack is too dark.
//
// TODO(emilio): We should probably allow the page to specify this one too:
// https://github.com/w3c/csswg-drafts/issues/6159
return nsNativeTheme::IsDarkColor(*mAccentColor) ? sColorWhite
: sColorBlack;
return sRGBColor::FromABGR(ComputeCustomAccentForeground(*mAccentColor));
}
sRGBColor GetLight() const {