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

Improve contrast of default theme #128

Closed
adamschwartz opened this issue Jul 20, 2020 · 13 comments
Closed

Improve contrast of default theme #128

adamschwartz opened this issue Jul 20, 2020 · 13 comments
Assignees
Labels
a11y Anything relating to accessibility.

Comments

@adamschwartz
Copy link

adamschwartz commented Jul 20, 2020

This is a great project! Thanks so much for making it.

While adding a high-contrast theme (as proposed by #99) would be great, I’m curious how you would feel about also improving the contrast of the default theme as well.

One component that jumped out at me was Tag. I don’t personally have any visually impairments, but I found the text of the tags in the example, particularly "Success" and "Warning", to be difficult to read.

Here are the contrast ratios (as calculated by Chrome DevTools1):

Perhaps the default theme could seek a WCAG AA rating (4.5:1 contrast or above). This would still leave plenty of room for the high-contrast theme to achieve a WCAG AAA rating (7:1 contrast or above).

As you’re aware, the colors scales are generated with a fixed lightness at every "tier".

// Generates custom properties with colors of lightness 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, and 95 percent
@mixin make-color-palette($name) {
@for $i from 5 through 95 {
@if $i % 5 == 0 {
--sl-color-#{$name}-#{$i}: hsl(var(--sl-color-#{$name}-hue), var(--sl-color-#{$name}-saturation), #{$i * 1%});
}
}
}

While the math is nice, the trouble with this approach is that perceived lightness varies with hue and saturation2.

Without getting too fancy, I’ll just say that if you take the 5 colors, which currently each have their HSL lightness property set to 50% and adjust them to 35, 30, 40, 30, and 40, respectively, you get this:

I personally find that much easier to read, but still "colorful" enough that that the text doesn’t read as "plain black".

With these adjustments to the colors, the contrast ratios are 4.85, 4.54, 5.14, 4.90, and 4.91, respectively. (So all WCAG AA.) And the math is still pretty nice. ;)

I hope this was helpful!


Footnotes

  1. WebAIM also has a great contrast checker.
  2. HSLuv is a great project which attempts to correct this issue.
@adamschwartz adamschwartz added the feature Feature requests. label Jul 20, 2020
@claviska
Copy link
Member

Thanks for the well-written, detailed issue. I agree — the text colors were chosen rather arbitrarily and I always thought they were a bit too light. Fixed in 57b8632 per your suggestion.

While the math is nice, the trouble with this approach is that perceived lightness varies with hue and saturation2.

This is why I'm super excited for browser to support LCH colors. It would definitely make generating theme colors more consistent!

Regarding the contrast checker — how did you generate that screenshot? I can't get Chrome or Firefox to show me contrast checking. Ended up having to copy the RGB color, convert it to hex, and paste it into WebAIM. 🤷🏻‍♂️

@adamschwartz
Copy link
Author

adamschwartz commented Jul 21, 2020

That’s terrific. Thanks so much for that quick response and change! I’m happy to help with an analysis of other components as well if you’d like.

This is why I'm super excited for browser to support LCH colors. It would definitely make generating theme colors more consistent!

100% yes—I can’t wait.

Regarding the contrast checker — how did you generate that screenshot?

Heh. I was wondering if you’d mention that. tl:dr; I faked it.


There are a couple of convenient ways to see contrast ratios in Chrome DevTools.

One way is to enter inspection mode, which you can enter with C (on macOS) or by clicking the top-left icon in the panel, depicted here:

Chrome DevTools

When you enter inspection mode, you will generally get a contrast ratio in the inspection popover. Here’s an example of inspecting the h1 on example.com:

Inspecting the h1 on example.com

The second way is to enter a color picker in the elements panel.

Chrome DevTools elements panel color picker

I haven’t spent too much time deeply investigating how these work under the covers, but it’s clear to me from using them, and from my general understanding of CSS, that these checkers have to make certain assumptions and don’t necessarily provide perfect results.

One assumption it has to make is what the background color is. There could be an absolutely positioned element which happens to be underneath the text that has a different background color than the getComputedStyle one, e.g. In general, any sort of layering or opacity can make it inaccurate (in terms of the perceived contrast).

Most relevant to your question, in the case of inspecting elements, the popover doesn’t always show the contrast ratio. I would bet there is a heuristic or a set of checks that it goes through, and if a certain condition isn’t met (so it thinks it can’t provide an accurate result), it aborts.

In the case of the Tag component, when you inspect the sl-tag element itself, you get an inaccurate result (in terms of perception) due to it using the inherited document text/background color:

Screenshot

When inspecting the inner <span> elements, the contrast doesn’t show:

Screenshot

Screenshot

So, I faked it. I copied the color/background-color from the inner <span> elements onto the sl-tag element, then inspected each and screenshotted the results, then finally cropped/arranged the screenshots.

If I had to guess, the issue with the inspector in this case has to do with the shadow DOM, and the additional complexities around layering that introduces. But that’s just a guess.

It’s unfortunate that this is case, but then again I’m so happy DevTools added the convenience of contrast ratio checking in the first place! So I can’t complain. ☺️ I would also bet the folks who made it know about its shortcomings and are working on improving it.

Thanks again for making the change!

@claviska
Copy link
Member

That's awesome. Thanks for taking the time to do it!

And as much as I've used "inspect," I never noticed that contract checker. 🤦🏻‍♂️

@claviska
Copy link
Member

claviska commented Jul 21, 2020

I’m happy to help with an analysis of other components as well if you’d like.

Forgot to mention that this would be great. The default theme should be AA for anything important. We'll save AAA for the high-contrast theme.

@adamschwartz
Copy link
Author

adamschwartz commented Jul 21, 2020

Amazing, that sounds great.

The Tab component is another low-hanging fruit for me:

Screenshot

What do you think would be the best way to tackle the work of making these changes in general?

@claviska
Copy link
Member

If it's a logical change, go ahead and submit a PR. If it's something that merits discussion (e.g. too drastic, doesn't look good, etc.), feel free to post an issue instead.

If you're not comfortable submitting PRs, I'm happy to make the changes myself if you provide a list of before/after values. 😄

@adamschwartz
Copy link
Author

adamschwartz commented Jul 22, 2020

To complete the work of making the core default theme components WCAG AA, assuming 5% lightness intervals, we’d need to make the following changes:

The following numbers represent the new lightness value needed for the HSL colors, as changed from 50%:

WCAG AA:

  • Tab (active state)
    • 40%
  • Button and Badge
    • 35% - primary
    • 30% - success
    • 40% - info
    • 30% - warning
    • 40% - danger

For Tab I think this change is great.

For Button and Badge however, I think we may not be particularly satisfied with the look.

After some experimentation, looking at the contrast ratios, I feel pretty good about at least the following compromise:

Compromise:

  • Button and Badge
    • 40% - primary
    • 35% - success
    • 45% - info
    • 35% - warning
    • 45% - danger

In some cases these come very close to AA.

So I’d recommend trying the full WCAG AA changes above, but if after seeing those, the colors seem too dark, the compromise values (5% lower in each case) would be a welcome alternative.

The rest of the components look great.

@claviska
Copy link
Member

For visual reference, here are the original colors:

CleanShot 2020-07-22 at 17 39 59@2x

Here are the AA compliant adjustments:

CleanShot 2020-07-22 at 17 37 58@2x

And here are the close-to-compliant adjustments:

CleanShot 2020-07-22 at 17 39 25@2x

While I feel that having AA compliance is a great goal, I don't think I'm comfortable with such a drastic change for these components. Some of the buttons look very dull to me, and they almost seem like they're depressed without interacting with them.

I'm open to tweaking other HSL values if necessary, so if anyone has design suggestions here I'd love to see some AA-compliant examples that look good throughout.

I'm also curious what other mainstream design systems and component libraries are doing in this regard. (Are they AA, close, or are they ignoring it?)

I'll have to think on this one a bit.

@claviska
Copy link
Member

I do agree that the current primary and the success colors are a bit bright, at least. 🤔

@claviska claviska reopened this Jul 22, 2020
@adamschwartz
Copy link
Author

adamschwartz commented Jul 22, 2020

Bootstrap comes close, with their lowest button scoring ~3.9. Something they do which helps is use a dark text color for the "warning" type.

image

Github’s comment button on this thread fails, at ~3.2.

So you’re in good company ;) I think we all can do better on this though.

A couple of my recent projects, including e.g. https://isbgpsafeyet.com, and https://web.scraper.workers.dev, use a UI library I’ve been privately building for some time, which I hope to open-source. Both of those sites exceed AA, nearing AAA for the crucial elements. And IMHO, they look pretty good.

That being said, the UI library defaults I have right now are still not so great, which is one of the reasons I still haven’t open-sourced it yet. So I totally can relate to how tough it can be for a more generic, less-opinionated, library to achieve AA out of the box.

Part of my interest in this project is actually that since it overlaps somewhat my own work, I’m hopeful that working with you and other upcoming component library authors, I can help the broader community solve these problems together, and move us all in a good direction.

It’s likely the case that some of the “hot” or “flashy” designs we’re used to from the last decade will need to be modified. Personally, for properties I design, it’s an easy to choice to improve color contrast at the potential cost of not having the “hottest” design. That being said, not every project has the same requirements: e.g. a personal project someone builds for a tablet display to be used in just their own home only needs to work for them.

Anything we can all do together is still something, and I think it’s good for us to challenge ourselves to come up with creative new designs that are accessible to everyone. There are definitely often tradeoffs here though, and I accept that it’s not always possible to please everyone.

I sincerely appreciate your thoughtful responses, and I’m excited to see Shoelace iterate over time. Cheers

@claviska claviska added a11y Anything relating to accessibility. and removed feature Feature requests. labels Jul 23, 2020
@claviska
Copy link
Member

claviska commented Jul 23, 2020

So you’re in good company ;) I think we all can do better on this though.

I agree. We can do better as designers. Screen readers (et al) can do better as assistive technologies. I feel like there's a point where we can all converge, but I don't think it should sacrifice creativity nor make things less appealing for the majority of users.

Having a high-contrast theme would be a great start. If we can provide users an easy way to offer it to their users, the default theme probably doesn't need to be held to the same standard. Not that we shouldn't care about it, but some of the creative restrictions can be relaxed.

I'd love to get to a point where there's an AA-compliant theme that's very similar to the default theme, then users can choose based on their needs and requirements. Maybe it can be enabled by default through prefers-contrast if that gets standardized and implemented.

I'm going to leave this open to encourage discussion. Thanks again for taking the time to research this!

@davidglezz
Copy link
Contributor

Try to make the star rating component accessible.
yellow is impossible, it would have to be changed to dark orange or red.
It's a shame because everything looks uglier

@claviska
Copy link
Member

With the color update that occurred in #283, contrast was improved a bit in most of the areas discussed in this thread. I'm still hoping to get around to designing a high-contrast theme (follow #99 for details), but for now I think I'm happy with where the default theme is.

If there are blatant contrast issues moving forward then feel free to post a new issue. 😄

claviska added a commit that referenced this issue Aug 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a11y Anything relating to accessibility.
Projects
None yet
Development

No branches or pull requests

3 participants