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

Use black and white as color-contrast fallback colors #30468

Merged
merged 10 commits into from
May 20, 2020

Conversation

ffoodd
Copy link
Member

@ffoodd ffoodd commented Mar 27, 2020

While trying to fix a few things related to #29315 I tried to increase the ratio against white threshold used in color-contrast() to 4.5.

This led to unexpected results, as I didn't totally understood what was going on this function: basically, we only test contrast against white, and if it fails to cross the threshold we use a dark foreground color instead.

This doesn't ensure that our dark foreground color will cross the threshold, neither than its contrast ratio with background will be better than white…

$indigo-300 in "Theming" is a good example where #fff doesn't meet 4.5:1 ratio required by WCAG 2 (giving only 4.06:1) but our $color-contrast-dark neither (defined as #212529 in _variables.scss, giving less than white: 3.8:1). FYI in that specific case, using #000 instead of #212529 makes it to 4.5:1.

Depending on the minimum contrast ratio defined, we'll always fail to meet 4.5 and increasing this $min-contrast-ratio would in fact lead to more insufficient contrasts everywhere — since white wouldn't match, we'd fallback to a worst value…).

I'd recommend the following:

  1. check if $color-contrast-light crosses the threshold; if so, return it;
  2. if not, check if $color-contrast-dark does; if so, return it;
  3. if not, check if white crosses the threshold; if so, return #fff;
  4. if not, check if black crosses the threshold; if so, return it.

If none of those lead to sufficient contrast ratio… Well, I don't know!

@twbs/css-review @patrickhlauke any opinion on this?

Preview: https://deploy-preview-30468--twbs-bootstrap.netlify.com/

@ffoodd ffoodd self-assigned this Mar 27, 2020
@ffoodd ffoodd requested review from a team and patrickhlauke March 27, 2020 10:59
@MartijnCuppens
Copy link
Member

LGTM. @ffoodd, could you check the PR content?

If none of those lead to sufficient contrast ratio… Well, I don't know!

Throw a warning and return the color with the most contrast

@ffoodd ffoodd force-pushed the feature/4.5-contrast-ratio branch from 5998f8d to 8b8f75e Compare March 27, 2020 13:01
@ffoodd ffoodd marked this pull request as ready for review March 27, 2020 15:52
@ffoodd
Copy link
Member Author

ffoodd commented Mar 27, 2020

To sum up changes:

  • new contrast-ratio() function to only return the ratio itself, as a number;
  • new most-contrasted() function to choose from $color-contrast-light, $color-contrast-dark, $white or $black the most contrasted one against color argument;
  • color-contrast() now loops through the four color candidates (in respective order):
    • returns the first one reaching $min-contrast-ratio,
    • populate a map with insufficiently contrasted colors — only used if none of the four options crosses the threshold,
    • in that case:
      • @warn to clarify things, mentionning $min-contrast-ratio and $background — the color argument passed to color-contrast(),
      • and return the most-contrasted() color in the four candidates.

To check the most-contrasted() function, you'll need to increase the $min-contrast-ratio to 7. You should get a dozen warnings, mostly in .btn-outline- variants.

Be sure to double-check things and play around: I increased the minimum contrast ratio to 4.5, which could affect every components…

To see obvious changes, please refer to the Theming page:

  1. this PR, with a 4.5:1 minimum contrast ratio: some intermediate colors like $blue-400 or $indigo-300 now have black text;
  2. master, with 3:1

Using Firefox's Accessibility DevTools, this PRs has 2 failures (excpeting anchor links "#") versus master which has 18; WAVE extension gives me 2 vs 18 too. The two failures are Success and Info swatches using .text-white utility…

@ffoodd ffoodd closed this Mar 27, 2020
@ffoodd ffoodd deleted the feature/4.5-contrast-ratio branch March 27, 2020 16:17
@ffoodd ffoodd restored the feature/4.5-contrast-ratio branch March 27, 2020 16:17
@ffoodd ffoodd reopened this Mar 27, 2020
@MartijnCuppens
Copy link
Member

The green button text is now black and white on hover, which feels a bit odd. Maybe we should darken the green color a bit? Maybe #048A24?

Other alternatives: https://contrast-finder.tanaguru.com/result.html;jsessionid=F3962634198A0E29FC7BB1F7793A7065?foreground=%23fff&background=%2328a745&ratio=4.5&isBackgroundTested=true&algo=Rgb&distanceSort=asc

@ffoodd
Copy link
Member Author

ffoodd commented Mar 30, 2020

Nice catch, I'll try this.

FYI I think buttons darkening on hover might be irrelevant too (look at warning or info buttons for examples). I'll think about it. They're all good.

However outline buttons for Warning, Info and Light aren't.

@ffoodd
Copy link
Member Author

ffoodd commented Mar 30, 2020

This PR works as intended.

While testing results, I came across three types of contrast failure through our docs — I fixed a few of them, the most straightforwards.

Color utilities

Utilities like .bg-warning or .text-warning, since modifying only background-color or color, can get very hard results — I fixed a few occurrences in docs (mostly cards) — but except applying both properties for each utility (which is irrelevant for Bootstrap, I guess) we just have to mention contrasts somewhere…

Bad component variants

Some components or items are conceptually unable to comply (for now):

Unfortunate examples

Some more in-depth examples should be reviewed: color schemes in navbar don't work well, but are only examples. Not quite sure about this kind of failures… But I think they can be quite common in our docs and example templates.

@ffoodd
Copy link
Member Author

ffoodd commented Mar 31, 2020

Reviewing related #25126, the Theming page is now fixed (at least with this PR).

Color utilities still have failures: .text-info, .text-black-50 and .text-white-50. FWIW, it could be prevented by adding a .bg-black utility, or associating $dark with $gray-900 instead of $gray-800 – this could lead to tons of improved contrasts everywhere.

Apart from those, #25126 would be fixed as of this PR.

@ffoodd
Copy link
Member Author

ffoodd commented Mar 31, 2020

So @twbs/css-review here's a summary, I don't really what to do with this.

  1. Some failures are inherent to the way we apply colors, but may be fixed in our examples at some point by ensuring we're always using background and color property with their best pairing color:
    • color and background utilites,
    • btn-outline (warning, info and light should be wrapped in a bg-dark container)
    • adding a .bg-black utility would help, mostly to use with $info color
    • and we should probably mention this in the Theming page (but the Color section in this PR provides working examples, so…).
    • what if we decide to pair those in utilities? Eg .bg-warning { background-color: $warning !important; color: $dark; } (notice not using !important here). Is that only possible with the Utility API?
  2. Some components or variants are using light grays as background, which messes up contrasts at some point: using links or .text-muted don't provide sufficient contrasts: we may override those in this kind of case (messy, code bloat, and specificity…) or find another way…
    • links are precisely 4.5:1 against white, so the only way around is to darken them — either in cases using light gray backgrounds, or globally.
    • .text-muted is 4.69:1, so there's some room to sufficient contrast is we lighten this gray again.

I think this should not be addressed in this PR, I already fixed the simplest examples and occurrences through our docs.

Should I open issues, make some PRs? Or wait and see, since we're already improving contrasts everywhere?

@mdo
Copy link
Member

mdo commented Apr 2, 2020

My only issue thus far with this is that the new green isn't the best visually—instead of matching with the overall color vibe, it feels like it sticks out as a forest green. However, I know green is notoriously difficult for getting color contrast right. I'd like to see what can be done with the colors before this gets merged.

To help with that, thoughts on putting together a colors page outside the docs (Examples or CodePen?) that includes our colors and their current contrast values against white and black?

@ffoodd ffoodd force-pushed the feature/4.5-contrast-ratio branch from 55010ff to 1fc5ec5 Compare April 7, 2020 09:39
@ffoodd
Copy link
Member Author

ffoodd commented Apr 7, 2020

@mdo just a POC for now but I temporarily display contrast ratios in main color swatches:

  1. current contrast ratio,
  2. contrast ratio against white,
  3. contrast ratio against black,
  4. with small color swatches à la Github to remind against which color the ratio is.

This is more to show you the values than to publish this — it's not accessible enough, I think — but was fairly the simplest way to show contrast ratio values since the only function to calculate them in Bootstrap resides in scss…

BTW I got the previous green back for now.

We may add a "Color Palette" example template, but I'm not convinced about its interest.

@ffoodd ffoodd force-pushed the feature/4.5-contrast-ratio branch 2 times, most recently from 95b6e0b to e0ab580 Compare April 7, 2020 15:25
@ffoodd
Copy link
Member Author

ffoodd commented Apr 17, 2020

@mdo Another approval on this? It'll help me a lot with other color-related topics :)

@ffoodd ffoodd force-pushed the feature/4.5-contrast-ratio branch from 4271ad6 to 2f40940 Compare April 17, 2020 13:07
@MartijnCuppens MartijnCuppens changed the title About color-contrast() failures Use black or white as color-contrast fallback colors Apr 18, 2020
Copy link
Member

@MartijnCuppens MartijnCuppens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with this, but want another approval from @mdo just to be sure.

@MartijnCuppens MartijnCuppens changed the title Use black or white as color-contrast fallback colors Use black and white as color-contrast fallback colors Apr 18, 2020
@ffoodd ffoodd force-pushed the feature/4.5-contrast-ratio branch from 2f40940 to 2988e48 Compare May 7, 2020 14:25
@ffoodd
Copy link
Member Author

ffoodd commented May 7, 2020

Made a few more tweaks to stick to the brand new "Customize" section :)

@mdo mdo mentioned this pull request May 12, 2020
@ffoodd
Copy link
Member Author

ffoodd commented May 13, 2020

@mdo friendly ping on this, since #30550 is on-hold from now on.

FYI, this PR now:

  1. improves color contrast choice by using #000 and #fff as fallbacks if none of $color-contrast-dark and $color-contrast-light provide sufficient contrast ratio;
  2. allow to use color-contrast() function with a fourth argument: $min-contrast-ratio — which can be handy to override the global value in specific cases (very small / large texts, for examples);
  3. adds contrast ratio scores in color swatches in the docs, to kind of document this;
  4. improves some cases where .text-* or .bg-* utilities weren't used appropriately, from an accessibility perspective.

This fourth point may be dropped, since it's partially covered by #30044 — or at least, would be solved differently in a more elegant way.

I'd like to see this merged before going on with colors :)

@ffoodd ffoodd force-pushed the feature/4.5-contrast-ratio branch from a24068d to df87acd Compare May 19, 2020 14:43
@ffoodd ffoodd force-pushed the feature/4.5-contrast-ratio branch from ebbc9ab to b138199 Compare May 19, 2020 14:59
@ffoodd ffoodd merged commit e1f3208 into master May 20, 2020
@ffoodd ffoodd deleted the feature/4.5-contrast-ratio branch May 20, 2020 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants