Tag: Accessible

Accessible SVG Icons

The answer to “What is the most accessible HTML for an SVG icon?” isn’t one-size-fits all, because what an icon needs to do on a website varies. I’m partial to Heather Migliorisi’s research on all this, but I can summarize.

The icon is decorative

As in, the icon is just sitting there looking pretty but it doesn’t matter if it entirely went away. If that’s the case:

<svg aria-hidden="true" ... ></svg>

There’s no need to announce the icon because the label next to it already does the job. So, instead of reading it, we hide it from screenreaders. That way, the label does what it’s supposed to do without the SVG stepping on its toes.

The icon is stand-alone

What we mean here is that the icon is unaccompanied by a visible text label, and is a meaningful action trigger on its own. This is a tricky one. It’s gotten better over time, where all you need for modern browsers is:

<svg role="img"><title>Good Label</title> ... </svg>. 

This works for an SVG inside a <button>, say, or if the SVG itself is playing the “button” role.

…and the link is the meaningful action. What’s important is that the link has good text. If the link has visible text, then the icon is decorative. If the SVG is the link where it’s wrapped in an <a> (rather than am internal-SVG link), then, give it an accessible label, like:

<a href="/" aria-label="Good Label"><svg aria-hidden="true" ... ></svg></a>

…or, have a <span class="screen-reader-only"> text within the link and the hidden SVG.


I believe this syncs up correctly with advice not only from Heather, but with Sara, Hugo, and Florens as well.


The post Accessible SVG Icons appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

,

Accessible Web Animation: The WCAG on Animation Explained

It’s true, web animation can be accessible! Sometimes it just takes a little extra effort to make sure that it is. There are strategic things we can do to make sure our animations have a positive impact on accessibility, like planning how they contribute to the overall UX and ease of use of our site. There are also more tactical considerations for making sure the animations on our site are accessible, and that’s where the Web Content Accessibility Guidelines (WCAG) comes in.

While different contexts can affect the details of what you need to do, the WCAG provides a number of recommendations for animated content and interactions. These include guidelines for when to provide pause and play controls, limits for blinking or flashing the screen, and advice on when to provide reduced motion options for users with motion sensitivities. If you haven’t looked at it in a while, the specification has been updated to version 2.1, and now has even more useful guidance on how we can design web animations that are accessible. 

Let’s dig into each of those recommendations in more detail to see how we can apply them to our work on the web:

Pause, Stop, Hide 

The first of the WCAG recommendations that applies specifically to animation is Pause, Stop, Hide. For this one, the title gives a pretty big clue into what the recommendation is all about. It states:

For any moving, blinking or scrolling information that (1) starts automatically, (2) lasts more than five seconds, and (3) is presented in parallel with other content, there is a mechanism for the user to pause, stop, or hide it unless the movement, blinking, or scrolling is part of an activity where it is essential; […]

The recommendation specifically applies to motion initiated by the web page without user interaction, and it might sound like something that doesn’t apply to UI animation work at first. Most of the durations we might use in UI animation work are far under this five second threshold individually. But there are some common patterns where this would apply. For example: auto-advancing carousels or slideshows, animated backgrounds, or animated illustrations. While each individual animation within these patterns might still be very short, the overall motion that is created often plays out over more than five seconds. This is especially true when these are designed to play on an infinite loop, which is most definitely longer than five seconds.

How to meet the Pause, Stop, Hide criteria

If you have some of these longer playing animations, you’ll need to add some kind of pause and play controls that allow users to control the motion and/or auto playing behaviour. The WCAG specification doesn’t dictate what these controls need to look like though, you have complete design control over that.

A good example of this in practice is how the article series “Dark Side of The Grid” handles the example animations. Each animated figure loops infinitely once it starts, so they provide a play/stop button for readers to play the animation when they want to see it, and stop it when they’re done. Other more decorative or illustrative animations in the article play once and then present a button to replay them, if users want to. The placement and design of the buttons also fits the aesthetic of the overall design of the article which makes them both functional and aesthetically pleasing. 

Animated GIFs are something to look out for too. If you’ve got a looping animated GIF, that’s going to need some sort of pause/play controls to successfully meet this criteria. Both of the techniques mentioned in this post are helpful for pulling that off. 

There are some exceptions for this recommendation, as noted by the WCAG. One exception specifically worth noting is loaders and preloaders.

Three flashes or below threshold 

This recommendation is one that probably has the most research behind it because it stems from the days of broadcast TV. The main reason behind this recommendation is that significant flashing on screen has been known to trigger seizures.

In short three flashes or below threshold states: 

Web pages do not contain anything that flashes more than three times in any one second period, or the flash is below the general flash and red flash thresholds.

How to meet the three flashes or below threshold criteria

The WCAG provides details on the size, ratio and viewing angle thresholds under which flashing the screen could be considered safe. But for most of us, it’s probably easiest to avoid anything that flashes more than three times in one second. I don’t think many UX designers set out to flash the screen excessively on purpose, but it can happen. For example, a design that’s going for a video game sort of feel or a glitchy vibe might involve some screen flashing that happens more frequently than three times in a second. 

One specific example of a design that includes a significant amount of flashing is this article from the Huffington Post, pictured below. It’s a highly stylized piece on how millennials have a tougher go at things like jobs and saving for retirement than previous generations. Its  glitchy 8-bit video game design is very on point with the theme of the article. Design-wise, it’s a great choice for the subject matter and is well executed. But there are times, as you can see from the frame-by-frame stills below, where the text color flashes more than three times a second. 

This amount of flashing could be problematic for people with epilepsy or other physical reactions triggered by flashing. To their credit, the Huffington Post also provided a text-only version of the article for anyone sensitive to flashing, as Eileen mentions in this post, as well as advanced warning of the potential flashing hazard.

In general, avoiding effects that require frequent flashing is the safest way to meet this criteria. However, If you can’t avoid flashing animations in your project the WCAG provides detailed instructions around the safe thresholds for flashing the screen. Also, providing advanced warning of flashing content and an alternate version of the content without the flashing effect (like the example above) is a good thing to do as well.  

The A, AA, and AAA levels of the WCAG 

The WCAG has multiple levels of criteria and conformance, which is why each recommendation has a notation of what level it falls under. Level A compliance is the minimum level of conformance. Level AA is the middle level of conformance and indicates that the criteria for both level A and AA have been met. Level AAA is the highest level of conformance and requires satisfying the criteria from level A, AA and AAA. Typically, the guidelines found in level AAA require additional effort to meet. (If you want to learn more about these levels and what’s included in them outside of the animation-related recommendations we’re covering here, I’ve put together a list of helpful resources at the end of this article.) 

In general, most people are aiming for level AA compliance when they say they are making an accessible website. This is also the level you might see requested in an RFP or project brief. The last two guidelines we discussed fall under the level AA criteria and, therefore, must be met to claim level AA compliance. The next guideline, however, is part of the level AAA criteria. Even though it’s outside of the typical level of conformance, it’s a very useful recommendation to take into consideration if your project relies significantly on animation. I highly recommend implementing it in your work.

Animation from interactions 

This guideline covers a different kind of animation than the previous two. While the first two are generally applied to animation that’s initiated by the web page itself, this one applies to animation initiated by user interaction. More specifically, it states: 

Motion animation triggered by interaction can be disabled, unless the animation is essential to the functionality or the information being conveyed.

At first read, the term “motion animation” can be confusing since we typically use the terms “motion” and “animation” interchangeably. It might seem overly specific at first, but it makes sense to get this specific in this case. The WCAG defines motion animation as animation that is used to ”create the illusion of movement”, and specifies that “motion animation does not include changes of color, blurring or opacity.”

Essentially, the term motion animation is used to indicate that certain types of animation create the sense of movement, while others do not. It’s those animations that create a sense of movement that concerns this guideline. It’s important to keep that distinction in mind when discussing animation and accessibility to help make sure you focus your efforts efficiently. If we were to express this distinction in a very eyeball-like Venn Diagram, it would look  like this:

A large light purple circle with the word Animation on it in white with a smaller white circle contained at the bottom of the larger circle with the word Motion on it in black.

Over the last few years, we’ve come to realize that some types of motion on screen, even as part of an interface, can cause people with motion sensitivities to become physically ill. So this is why we might want to consider creating a reduced motion mode in our  work. I wrote more about the kinds of motion effects that are most likely to be triggering in this article, and this post from the WebKit blog covers some examples in detail.

How to meet the animation from interactions criteria

The WCAG suggests we avoid unnecessary animation, provide a control for users to turn off any non-essential motion, or take advantage of the reduced motion setting in operating systems and user agents. Let’s look at each of these in a bit more detail. There are a few different things we can do to help avoid exposing people to animation that might make them dizzy, nauseous, or worse.

Avoid unnecessary animation

Context and expectations also play a role here. The amount of motion you might reasonably expect to encounter on a website for a movie or video game is very different from what you might reasonably expect to encounter on say a government site or construction company’s site. The same amazing effects that might fit in just fine on a video game’s site would feel unnecessary or out of place on, say, a government website. Consider the context and expectations that apply to your site and whether the amount of animation you’re using in your design fits that context. 

Provide a way for users to turn off potentially problematic motion animation

If you have motion in your product that might be a trigger for folks with motion sensitivities, providing a way for users to avoid those triggering animations is the responsible thing to do. Based on the WCAG’s definition, any effect that could be considered motion animation should be one that includes a reduced version. 

Parallax effects are a good example. Those are universally problematic for folks with motion sensitivities based on my own research, yet it’s also still a very popular technique. While it wouldn’t be realistic to call for an end to all parallax effects entirely, implementing parallax responsibly requires giving your users some level of control to turn off that triggering motion. 

Typically, this is interpreted as including a toggle, setting, or preference for users to indicate their preference for reduced motion, and providing reduced versions of those motion animation effects when it’s activated. The Netlify 1 Million Devs site is one example of a motion toggle in action, and the official Animal Crossing site has one too.

Showing a screenshot of Netlify's Thanks a Million webpage. A toggle to disable animation is located in the top left corner of the page, above the content, which is set against a mint green background.
Take advantage of the reduce motion feature 

Sites or apps that don’t rely heavily on large amounts of motion might find that a custom toggle isn’t the right strategy for them, and instead use the prefers-reduced-motion media query on its own. This allows you to provide a reduced version of highly animated content when that preference is present globally via the user’s operating system. It’s also a setting they can set in one place and have it affect a variety of content they encounter. That makes it a great tool for us to use to detect and respond to a user’s need for reduced motion. 

I’ve written about using prefers-reduced-motion in detail over at Smashing Magazine, and it’s also been covered by other articles on this site. In short, it allows us to access someone’s OS-level motion preference via a media query. We can access it in CSS or JavaScript and use the returned value to provide a reduced motion experience for those who want it. For example, we could do this to create a reduced motion variation of a bouncing CSS animation:  

/* A constant bouncing motion effect applied to the title */ h2 {   animation: bouncing 1.5s linear infinite alternate; }  /* Replace it with a safer effect when prefers-reduced-motion returns true */ @media (prefers-reduced-motion: reduce) {   h2 {     animation: fade 0.5s ease-in both;   } }

Some sites opt to use both a custom toggle and reduced motion preferences together. If you go to the site with reduced motion requested in your operating system settings, you automatically get the reduced motion mode. This two-pronged approach is a great strategy for sites with large amounts of motion. Marcy Sutton covers the basics of how to set up this approach in her egghead.io course, as well as in this CodePen demo

Use these guidelines for your next animation project

There you have it, everything the WCAG says about animation explained in one place. I hope this article will help you to confidently make your web animation work accessible. Sometimes it takes a little extra effort, but that extra effort is totally worth it when it means you’ve expanded the number of people who can meaningfully interact with your site.

This article focused on the recommendations specific to animation, but animation isn’t the only place in our work where accessibility considerations can make a big impact. There are some great resources on accessibility out there that cover a more holistic view on accessibility. One of my favorites is the book Accessibility for Everyone by Lara Kalbag. Sites like WebAIM and the A11y Project are great ones to check out for a wealth of resources. If you’re doing a lot of your animation work with SVG, Heather’s SVG accessibility article is a good resource as well. I highly recommend checking out these resources if you haven’t already. 


The post Accessible Web Animation: The WCAG on Animation Explained appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , ,
[Top]

Creating an Accessible Range Slider with CSS

, , ,
[Top]

Accessible Font Sizing, Explained

The Web Content Accessibility Guidelines (WCAG), an organization that defines standards for web content accessibility, does not specify a minimum font size for the web.

But we know there’s such a thing as text that is too small to be legible, just as text that can be too large to consume. So, how can we make sure our font sizes are accessible? What sort of best practices can we rely on to make for an accessible reading experience?

The answer: it’s not up to us. It Depends™. We’ll get into some specific a bit later but, for now, let’s explore the WCAG requirements for fonts.

Sizing, contrast, and 300 alphabets

First, resizing text.  We want to provide users with low vision a way to choose how fonts are displayed. Not in a crazy way. More like the ability to increase the size by 200% while maintaining readability and avoiding content collisions and overlaps.

Secondly, there’s contrast. This is why I said “it depends” on what makes an accessible font size. Text has to follow a contrast ratio of at least 4.5:1, with the exception of a large-scale text that should have a contrast ratio of at least 3:1. You can use tools like WebAIM’s Contrast Checker to ensure your text meets the guidelines. Stacy Arrelano’s deep dive on color contrast provides an excellent explanation of how contrast ratios are calculated.

A contrast ratio of 2.39 to 1 would not pass any of the WCAG checks, a ratio of 4.65 to 1 would pass only the AA check for normal text sizes and a 10.09 to 1 contrast ratio would pass both AA and AAA WCAG checks.
Example of three color contrast measurements and their WCAG test results according to WebAIM’s contrast checker.

There are around 300 alphabets in the world. Some characters are simple and readable in smaller sizes, others are incredibly complex and would lose vital details at the same size. That’s why specs cannot define a font size that meets the specification for contrast ratios.

And when we talk about “text” and “large text” sizes, we’re referring to what the spec calls “the minimum large print size used for those languages and the next larger standard large print size.” To meet AAA criteria using Roman text, for example, “large” is 18 points. Since we live in a world with different screen densities, specs measure sizes in points, not pixels, and in some displays, 18pt is equal to 24px. For other fonts, like CJK (Chinese, Japanese, Korean) or Arabic languages, the actual size in pixel would be different. Here’s the word “Hello” compared next to three other languages:

Hello สวัสดี مرحبا 你好

In short, WCAG specifies contrast instead of size.

The WCAG recommended font size for large text has greater contrast than something half the size. Notice how a larger font size lets in more of the background that sits behind the text.

Here is the good news: a browser’s default styles are accessible and we can leverage them to build an accessible font size strategy. Let’s see how.

Think about proportions, not size

The browser first loads its default styles (also known as the “User Agent stylesheet”), then those cascade to the author’s styles (the ones we define), and they both cascade and get overwritten by the user’s styles.

As Adrian Sandu mentions in his article about rem CSS units:

[…] there is an empirical study run by the people behind the Internet Archive showing that there is a significant amount of users who change their default font size in the browser settings.

We don’t fully control the font-family property, either. The content might be translated, the custom font family might fail to load, or it might even be changed. For example, OpenDyslexic is a typeface created to increase readability for readers with dyslexia. In some situations, we may even explicitly allow switching between a limited set of fonts

Therefore, when defining fonts, we have to avoid hindering the ability of a user or a device to change our styles and let go of assumptions: we just don’t know where our content is going to land and we can’t be sure about the exact size, language, or font that’s used to display content.

But there is one thing that we can control: proportions.

By using CSS relative units, we can set our content to be proportional to whatever the environment tells it to be. WCAG recommends using em units to define font size. There are several publications discussing the benefits of using ems and rems and it’s beyond the scope of this article. What I’d say here is to use rems and ems for everything, even for other properties besides font-size (with the exception of borders, where I use pixels).

Avoid setting a base font-size

My recommendation is to avoid setting font-size on the :root, <html> or <body> elements in favor of letting the browser’s default size serve as a baseline from where we can cascade our own styles. Since this default is accessible, the content will also be accessible. The WACAG 2.2 working draft states that:

When using text without specifying the font size, the smallest font size used on major browsers for unspecified text would be a reasonable size to assume for the font.

Of course, there is an exception to the rule. When using an intricate, thin, or super short x-height font, for example, you might consider bumping up the font size base to get the correct contrast. Remember that the spec defines contrast, not size:

Fonts with extraordinarily thin strokes or unusual features and characteristics that reduce the familiarity of their letter forms are harder to read, especially at lower contrast levels.

In the same manner, a user might change the base font size to fit their needs. A person with low vision would want to choose a larger size, while someone with an excellent vision can go smaller to gain real estate on their screens.

It’s all about proportions: we define how much larger or smaller parts of the content should be by leveraging the default base to set the main text size.

:root {   /* Do not set a font-size on a :root, body nor html level */   /* Let your main text size be decided by the browser or the user settings */  } .small {   font-size: .8rem; } .large {   font-size: 2rem; }

What about headings?

Since headings create a document outline that helps screenreaders navigate a document, we aren’t defining type selectors for heading sizes. Heading order is a WCAG criteria: the heading elements should be organized in descending order without skipping a level, meaning that an h4 should come right after an h3.

Sometimes resetting the font sizing of all headings to 1rem is a good strategy to make the separation of the visual treatment from the meaning mandatory.

How can we work with pixels?

Both rem or em sizing is relative to something else. For example, rem  calculates size relative to the <html>  element, where em is calculated by the sizing of its own element. It can be confusing, particularly since many of us came up working exclusively in pixels.

So, how can we still think in pixels but implement relative units?

More often than not, a typographical hierarchy is designed in pixels. Since we know about user agent stylesheets and that all major browsers have a default font size of 16px, we can set that size for the main text and calculate the rest proportionately with rem units.

Browser Name Base Font Size
Chrome v80.0 16px
FireFox v74.0 16px
Safari v13.0.4 16px
Edge v80.0 (Chromium based) 16px
Android (Samsung, Chrome, Firefox) 16px
Safari iOS 16px
Kindle Touch 26px (renders as 16px since it’s a high density screen)

Now let’s explore three methods for using relative sizing in CSS by converting those pixels to rem units.

Method 1: The 62.5% rule

In order to seamlessly convert pixels to rem, we can set the root sizing to 62.5%. That means 1rem equals 10px:

:root {   font-size: 62.5%; /* (62.5/100) * 16px = 10px */   --font-size--small: 1.4rem; /* 14px */   --font-size--default: 1.6rem; /* 16px */   --font-size--large: 2.4rem; /* 24px */ } 
 .font-size--small {   font-size: var(--font-size--small); }  .font-size--default {   font-size: var(--font-size--default); }  .font-size--large {   font-size: var(--font-size--large); }

Method 2: Using the calc() function

We can also calculate sizes with CSS calc() by dividing the pixel value by the font base we assume most browsers have:

:root {   --font-size--small: calc((14/16) * 1rem); /* 14px */   --font-size--default: calc((16/16) * 1rem); /* 16px */   --font-size--large: calc((24/16) * 1rem); /* 24px */ } 
 .font-size--small {   font-size: var(--font-size--small); }  .font-size--default {   font-size: var(--font-size--default); }  .font-size--large {   font-size: var(--font-size--large); }

Method 3: Using a “pixel-to-rem” function

Similar to calc() , we can leverage a preprocessor to create a “pixel-to-rem” function. There are implementations of this in many flavors, including this Sass mixin and styled-components polish.

:root {   --font-size--small: prem(14); /* 14px */   --font-size--default: prem(16); /* 16px */   --font-size--large: prem(24); /* 24px */ } 
 .font-size--small {   font-size: var(--font-size--small); }  .font-size--default {   font-size: var(--font-size--default); }  .font-size--large {   font-size: var(--font-size--large); }

It’s even possible to create a “pixel-to-rem” function with vanilla CSS:

Embrace a diverse web!

The bottom line is this: we don’t have control over how content is consumed. Users have personal browser settings, the ability to zoom in and out, and various other ways to customize their reading experience. But we do have best CSS best practices we can use to maintain a good user experience alongside those preferences:

  • Work with proportions instead of explicit sizes.
  • Rely on default browser font sizes instead of setting it on the :root, <html> or <body>.
  • Use rem units to help scale content with a user’s personal preferences.
  • Avoid making assumptions and let the environment decide how your content is being consumed.

Special thanks to Franco Correa for all the help writing this post.

The post Accessible Font Sizing, Explained appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Programming Sass to Create Accessible Color Combinations

We’re all looking for low-hanging fruit to make our sites and apps more accessible. One of the easier things we can do is make sure the colors we use are easy on the eyes. High color contrast is something that benefits everyone. It not only reduces eye strain in general, but is crucial for folks who deal with reduced vision.

So let’s not only use better color combinations in our designs but find a way to make it easier for us to implement high contrasts. There’s one specific strategy we use over at Oomph that lets a Sass function do all the heavy lifting for us. I’ll walk you through how we put that together.

Want to jump right to the code because you already understand everything there is to know about color accessibility? Here you go.

What we mean by “accessible color combinations”

Color contrast is also one of those things we may think we have handled. But there’s more to high color contrasts than eyeballing a design. There are different levels of acceptable criteria that the WCAG has defined as being accessible. It’s actually humbling to crack open the WebAIM Contrast Checker and run a site’s color combinations through it.

My team adheres to WCAG’s Level AA guidelines by default. This means that: 

  • Text that is 24px and larger, or 19px and larger if bold, should have a Color Contrast Ratio (CCR) of 3.0:1.
  • Text that is smaller than 24px should have a CCR of 4.5:1.

If a site needs to adhere to the enhanced guidelines for Level AAA, the requirements are a little higher:

  • Text that is 24px and larger, or 19px and larger if bold, should have a CCR of 4.5:1.
  • Text that is smaller than 24px should have a CCR of 7:1.

Ratios? Huh? Yeah, there’s some math involved here. But the good news is that we don’t need to do it ourselves or even have the same thorough understanding about how they’re calculated the way Stacie Arellano recently shared (which is a must read if you’re into the science of color accessibility).

That’s where Sass comes in. We can leverage it to run difficult mathematical computations that would otherwise fly over many of our heads. But first, I think it’s worth dealing with accessible colors at the design level.

Accessible color palettes start with the designs

That’s correct. The core of the work of creating an accessible color palette starts with the designs. Ideally, any web design ought to consult a tool to verify that any color combinations in use pass the established guidelines — and then tweak the colors that don’t. When our design team does this, they use a tool that we developed internally. It works on a list of colors, testing them over a dark and a light color, as well as providing a way to test other combinations. 

ColorCube provides an overview of an entire color palette, showing how each color performs when paired with white, black, and even each other. It even displays results for WCAG Levels AA and AAA next to each result. The tool was designed to throw a lot of information at the user all at once when evaluating a list of colors.

This is the first thing our team does. I’d venture to guess that many brand colors aren’t chosen with accessibility at the forefront. I often find that those colors need to change when they get translated to a web design. Through education, conversation, and visual samples, we get the client to sign off on the new color palette. I’ll admit: that part can be harder than the actual work of implementing accessible colors combinations.

The Color Contrast Audit: A typical design delivery when working with an existing brand’s color palette. Here, we suggest to stop using the brand color Emerald with white, but use an “Alt” version that is slightly darker instead. 

The problem that I wanted to solve with automation are the edge cases. You can’t fault a designer for missing some instance where two colors combine in an unintended way — it just happens. And those edge cases will come up, whether it is during the build or even a year later when new colors are added to the system.

Developing for accessibility while keeping true to the intent of a color system

The trick when changing colors to meet accessibility requirements is not changing them so much that they don’t look like the same color anymore. A brand that loves its emerald green color is going to want to maintain the intent of that color — it’s “emerald-ness.” To make it pass for accessibility when it is used as text over a white background, we might have to darken the green and increase its saturation. But we still want the color to “read” the same as the original color.

To achieve this, we use the Hue Saturation Lightness (HSL) color model. HSL gives us the ability to keep the hue as it is but adjust the saturation (i.e. increase or decrease color) and lightness (i.e. add more black or more white). The hue is what makes a green that green, or a blue that blue. It is the “soul” of the color, to get a little mystical about it. 

Hue is represented as a color wheel with a value between 0° and 360° — yellow at 60°, green at 120°, cyan at 180°, etc. Saturation is a percentage ranging from 0% (no saturation) to 100% (full saturation). Lightness is also a value that goes from 0% to 100%, where no lightness is at 0%, no black and no white is at 50%, and 100% is all lightness, or very light.

A quick visual of what tweaking a color looks like in our tool:

With HSL, changing the low-contrast green to a higher contrast meant changing the saturation from 63 to 95 and the lightness from 45 to 26 on the left. That’s when the color gets a green check mark in the middle when used with white. The new green still feels like it is in the same family, though, because the Hue remained at 136, which is like the color’s “soul.”

To learn more, play around with the fun HSL visualizer mothereffinghsl.com. But for a more in-depth description of color blindness, WCAG color contrast levels, and the HSL color space, we wrote an in-depth blog post about it.

The use case I want to solve

Designers can adjust colors with the tools that we just reviewed, but so far, no Sass that I have found could do it with mathematical magic. There had to be a way. 

These are some similar approaches I have seen in the wild:

  • An idea by Josh Bader uses CSS variables and colors split into their RGB values to calculate whether white or black is the best accessible color to use in a given situation.
  • Another idea by Facundo Corradini does something similar with HSL values and a very cool “switch function” in CSS.

I didn’t like these approaches. I didn’t want to fallback to white or black. I wanted colors to be maintained but adjusted to be accessible. Additionally, changing colors to their RGB or HSL components and storing them with CSS variables seemed messy and unsustainable for a large codebase.

I wanted to use a preprocessor like Sass to do this: given two colors, automagically adjust one of them so the pair receives a passing WCAG grade. The rules state a few other things to consider as well — size of the text and whether or not the font is bold. The solution had to take this into account. 

In code terms, I wanted to do this:

// Transform this non-passing color pair: .example {   background-color: #444;   color: #0094c2; // a 2.79 contrast ratio when AA requires 4.5   font-size: 1.25rem;   font-weight: normal; } 
 // To this passing color pair: .example {   background-color: #444;   color: #00c0fc; // a 4.61 contrast ratio   font-size: 1.25rem;   font-weight: normal; }

A solution that does this would be able to catch and handle those edge cases we mentioned earlier. Maybe the designer accounted for a brand blue to be used over a light blue, but not a light gray. Maybe the red used in error messages needs to be tweaked for this one form that has a one-off background color. Maybe we want to implement a dark mode feature to the UI without having to retest all the colors again. These are the use cases I had in mind going into this. 

With formulas can come automation

The W3C has provided the community with formulas that help analyze two colors used together. The formula multiplies the RGB channels of both colors by magic numbers (a visual weight based on how humans perceive these color channels) and then divides them to come up with a ratio from 0.0 (no contrast) to 21.0 (all the contrast, only possible with white and black). While imperfect, this is the formula we use right now:

If L1 is the relative luminance of a first color  And L2 is the relative luminance of a second color, then - Color Contrast Ratio = (L1 + 0.05) / (L2 + 0.05) Where - L = 0.2126 * R + 0.7152 * G + 0.0722 * B And - if R sRGB <= 0.03928 then R = R sRGB /12.92 else R = ((R sRGB +0.055)/1.055) ^ 2.4 - if G sRGB <= 0.03928 then G = G sRGB /12.92 else G = ((G sRGB +0.055)/1.055) ^ 2.4 - if B sRGB <= 0.03928 then B = B sRGB /12.92 else B = ((B sRGB +0.055)/1.055) ^ 2.4 And - R sRGB = R 8bit /255 - G sRGB = G 8bit /255 - B sRGB = B 8bit /255

While the formula looks complex, it’s just math right? Well, not so fast. There is a part at the end of a few lines where the value is multiplied by a decimal power — raised to the power of 2.4. Notice that? Turns out that it’s complex math which most programming languages can accomplish — think Javascript’s math.pow() function — but Sass is not powerful enough to do it. 

There’s got to be another way…

Of course there is. It just took some time to find it. 🙂

My first version used a complex series of math calculations that did the work of decimal powers within the limited confines of what Sass can accomplish. Lots of Googling found folks much smarter than me supplying the functions. Unfortunately, calculating only a handful of color contrast combinations increased Sass build times exponentially. So, that means Sass can do it, but that does not mean it should. In production, build times for a large codebase could increase to several minutes. That’s not acceptable. 

After more Googling, I came across a post from someone who was trying to do a similar thing. They also ran into the lack of exponent support in Sass. They wanted to explore “the possibility of using Newtonian approximation for the fractional parts of the exponent.” I totally understand the impulse (not). Instead, they decided to use a “lookup table.” It’s a genius solution. Rather than doing the math from scratch every time, a lookup table provides all the possible answers pre-calculated. The Sass function retrieves the answer from the list and it’s done.

In their words:

The only part [of the Sass that] involves exponentiation is the per-channel color space conversions done as part of the luminance calculation. [T]here are only 256 possible values for each channel. This means that we can easily create a lookup table.

Now we’re cooking. I had found a more performant direction. 

Usage example

Using the function should be easy and flexible. Given a set of two colors, adjust the first color so it passes the correct contrast value for the given WCAG level when used with the second color. Optional parameters will also take the font size or boldness into account.

// @function a11y-color( //   $ color-to-adjust, //   $ color-that-will-stay-the-same, //   $ wcag-level: 'AA', //   $ font-size: 16, //   $ bold: false // ); 
 // Sass sample usage declaring only what is required .example {   background-color: #444;   color: a11y-color(#0094c2, #444); // a 2.79 contrast ratio when AA requires 4.5 for small text that is not bold } 
 // Compiled CSS results: .example {   background-color: #444;   color: #00c0fc; // which is a 4.61 contrast ratio }

I used a function instead of a mixin because I preferred the output of a single value independent from a CSS rule. With a function, the author can determine which color should change. 

An example with more parameters in place looks like this:

// Sass .example-2 {   background-color: a11y-color(#0094c2, #f0f0f0, 'AAA', 1.25rem, true); // a 3.06 contrast ratio when AAA requires 4.5 for text 19px or larger that is also bold   color: #f0f0f0;   font-size: 1.25rem;   font-weight: bold; } 
 // Compiled CSS results: .example-2 {   background-color: #087597; // a 4.6 contrast ratio   color: #f0f0f0;   font-size: 1.25rem;   font-weight: bold; }

A deeper dive into the heart of the Sass function

To explain the approach, let’s walk through what the final function is doing, line by line. There are lots of helper functions along the way, but the comments and logic in the core function explain the approach:

// Expected: // $ fg as a color that will change // $ bg as a color that will be static and not change // Optional: // $ level, default 'AA'. 'AAA' also accepted // $ size, default 16. PX expected, EM and REM allowed // $ bold, boolean, default false. Whether or not the font is currently bold // @function a11y-color($ fg, $ bg, $ level: 'AA', $ size: 16, $ bold: false) {   // Helper: make sure the font size value is acceptable   $ font-size: validate-font-size($ size);   // Helper: With the level, font size, and bold boolean, return the proper target ratio. 3.0, 4.5, or 7.0 results expected   $ ratio: get-ratio($ level, $ font-size, $ bold);   // Calculate the first contrast ratio of the given pair   $ original-contrast: color-contrast($ fg, $ bg);      @if $ original-contrast >= $ ratio {     // If we pass the ratio already, return the original color     @return $ fg;   } @else {     // Doesn't pass. Time to get to work     // Should the color be lightened or darkened?     // Helper: Single color input, 'light' or 'dark' as output     $ fg-lod: light-or-dark($ fg);     $ bg-lod: light-or-dark($ bg); 
     // Set a "step" value to lighten or darken a color     // Note: Higher percentage steps means faster compile time, but we might overstep the required threshold too far with something higher than 5%     $ step: 2%;          // Run through some cases where we want to darken, or use a negative step value     @if $ fg-lod == 'light' and $ bg-lod == 'light' {       // Both are light colors, darken the fg (make the step value negative)       $ step: - $ step;     } @else if $ fg-lod == 'dark' and $ bg-lod == 'light' {       // bg is light, fg is dark but does not pass, darken more       $ step: - $ step;     }     // Keeping the rest of the logic here, but our default values do not change, so this logic is not needed     //@else if $ fg-lod == 'light' and $ bg-lod == 'dark' {     //  // bg is dark, fg is light but does not pass, lighten further     //  $ step: $ step;     //} @else if $ fg-lod == 'dark' and $ bg-lod == 'dark' {     //  // Both are dark, so lighten the fg     //  $ step: $ step;     //}          // The magic happens here     // Loop through with a @while statement until the color combination passes our required ratio. Scale the color by our step value until the expression is false     // This might loop 100 times or more depending on the colors     @while color-contrast($ fg, $ bg) < $ ratio {       // Moving the lightness is most effective, but also moving the saturation by a little bit is nice and helps maintain the "power" of the color       $ fg: scale-color($ fg, $ lightness: $ step, $ saturation: $ step/2);     }     @return $ fg;   } }

The final Sass file

Here’s the entire set of functions! Open this in CodePen to edit the color variables at the top of the file and see the adjustments that the Sass makes:

All helper functions are there as well as the 256-line lookup table. Lots of comments should help folks understand what is going on. 

When an edge case has been encountered, a version in SassMeister with debug output was helpful while I was developing it to see what might be happening. (I changed the main function to a mixin so I can debug the output.) Feel free to poke around at this as well.

Play with this gist on SassMeister.

And finally, the functions have been stripped out of CodePen and put into a GitHub repo. Drop issues into the queue if you run into problems. 

Cool code! But can I use this in production?

Maybe. 

I’d like to say yes, but I’ve been iterating on this thorny problem for a while now. I feel confident in this code but would love more input. Use it on a small project and kick the tires. Let me know how the build time performs. Let me know if you come across edge cases where passing color values are not being supplied. Submit issues to the GutHub repo. Suggest improvements based on other code you’ve seen in the wild. 

I’d love to say that I have Automated All the A11y Things, but I also know it needs to be road-tested before it can be called Production Ready™. I’m excited to introduce it to the world. Thanks for reading and I hope to hear how you are using it real soon.

The post Programming Sass to Create Accessible Color Combinations appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Building an accessible autocomplete control

Here’s a great in-depth post from Adam Silver about his journey to create an autocomplete field that’s as accessible as possible. There are so many edge cases to consider! There are old browsers and their peculiar quirks, there are accessibility best practices for screen readers, and not to mention dealing with the component design when there’s no JavaScript, etc.

Adam offers a warning before he begins:

[…] I’ve been looking at ways to let users enter a destination country. Unfortunately, native HTML form controls just aren’t good enough for this type of interaction. And so we need to build a custom autocomplete control from scratch. A word of warning though: this is one of the hardest UI components I’ve ever had to make—they’re just way harder than they look.

I also just bought Adam’s book, Form Design Patterns, and this post now makes me extra excited to read it.

Direct Link to ArticlePermalink

The post Building an accessible autocomplete control appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Why Are Accessible Websites so Hard to Build?

I was chatting with some front-end folks the other day about why so many companies struggle at making accessible websites. Why are accessible websites so hard to build? We learn about HTML, we make sure things are semantic and — voila! @— we have an accessible website. During the course of conversation, someone mentioned the Domino’s pizza legal case, which is perhaps the most public example of a company being sued because of a lack of accessibility.

Here’s an interesting tidbit from that link:

According to CNBC, the number of lawsuits over inaccessible websites jumped 58 percent last year over 2017, to more than 2,200.

Inaccessible websites are not just a consideration for designers and engineers but a serious problem for a company’s legal team as well. Thankfully, it seems more of these cases will be brought to trial and (my personal hope is) this will get folks to care more about semantics and front-end development best practices. Although I’d like to think that companies would do what’s best for the web and make websites that meet the baseline requirements without a legal threat, we absolutely need to make inaccessible websites illegal for folks to really pay attention to this issue.

However! I also worry about attributing what might simply be a lack of knowledge to malice. I reckon a lot of websites have bad accessibility not because folks don’t care, but because they don’t know there’s an issue in the first place. As my conversation with front-end engineers progressed, I realized that the reason accessibility isn’t tackled seriously probably doesn’t have anything to do with bandwidth, or experience, or money.

I reckon the problem is that the accessibility of a website can be invisibly and silently broken.

Here’s an example: when developing a site, JavaScript errors are probably going to be caught because everything breaks if something goes wrong. And CSS bugs are going to get caught because something will look off. But the accessibility or performance of a website can go from okay to terrible overnight and with no warning whatsoever. Yhe only way to fix these invisibly broken things is to first make them visible.

So, here’s an idea: what if our text editors caught accessibility issues and showed them to us during development? It could look something like this:

An example of how performance and accessibility issues might be flagged in VS Code whilst you type.

I’m sure there are a ton of other ways we can make accessibility issues more public and visible. There are tools such as Lighthouse and browser extensions that are already out there, but making accessibility (and even performance, another silent fail) a part of our minute-to-minute workflow ensures that we can’t ignore it. Something like this would encourage us to learn about the problems, give us links to potential solutions, and encourage us all to care for a relatively misunderstood part of front-end development.

The post Why Are Accessible Websites so Hard to Build? appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Designing accessible color systems

The team at Stripe explores how they’re refining their color palette to make it more accessible and legible for users across all their products and interfaces. Not only that but the team built a wonderful and yet entirely bonkers app for figuring out the ideal range of colors that they needed.

We built a web interface to allow us to visualize and manipulate our color system using perceptually uniform color models. The tool gave us an immediate feedback loop while we were iterating on our colors—we could see the effect of every change.

This tool is…whoa! I would love to learn a bit more about why they built this though as it looks like it wouldn’t have been a particularly quick and easy thing to put together. I wonder if that team has to support a wide-range of colors for their charts or data-visualization UI (as complex charts can often require a much larger range of colors for comparing bits of data effectively). Either way, this is pretty inspiring work.

This somewhat harkens to a couple of techniques for enforcing accessible colors, including one that uses custom properties with calc() and rgb by Josh Bader, and another by Facundo Corradini that also uses custom properties but with hsl with conditional statements.

Direct Link to ArticlePermalink

The post Designing accessible color systems appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Mina Markham Should Make Beyoncé’s Site Accessible

, , , , ,
[Top]

A More Accessible Portals Demo

The point of the <portal> element (behind a flag in Chrome Canary) is that you can preload another whole page (like <iframe>), but then have APIs to animate it to the current page. So “Single Page App”-like functionality (SPA), but natively. I think that’s pretty cool. I’m a fan of JavaScript frameworks in general, when they are providing value by helping do things that are otherwise difficult, like fancy state management, efficient re-rendering, and component composition. But if the framework is being reached for just for SPA qualities, that’s unfortunate. The web platform is at its best when it seems what people are doing are in step with native, standardized solutions.

But it’s not the web platform at its best when things are done inaccessibly. Steve Faulkner wrote “Short note on the portal element” where he points out seven issues with the portal element as it exists now. Here’s a demo of it with some of those issues addressed. I guess it’s somewhat of an implementation issue if a lot can be fixed from the outside, but I imagine much of it cannot (e.g. back button behavior, whether the loaded pages becomes part of the accessibility tree, etc.).

Here’s a video of the basic behavior:

Direct Link to ArticlePermalink

The post A More Accessible Portals Demo appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]