A primer on web accessibility

September 01, 2019

This post has been repurposed for the ACLU's Tech & Analytics blog! You can check it out below:

How we made aclu.org more accessible

Let's be real: the state of accessibility on the web is abysmal. On the bright side, there is room for radical improvement.

One of the most important realizations I had when doing research on accessible web development was that you can't just add some ARIA tags and alt text and call it a day. Rather, developing for accessibility means a working towards degrees of improvement for a diverse set of users, often involving difficult tradeoffs. Accessibility is a philosophy and design mindset to add to your toolkit - one that's really rewarding when practiced.

A note on accessibility tech

While laptops and smartphones tend to be the most visible types of devices, many people who use the internet do so via keyboard or an assistive device. Some who use keyboards use a keyboard overlay (helpful for cognitive or motor disabilities), and others use tab key to navigate through the interactive parts of a site.

Screenreaders are also popular among those who are blind or visually impaired, and exist for mobile and desktop. Essentially, they do a sweep through the DOM, picking up available content, and read out that content to the user as they navigate through the page. JAWS and TalkBack are popular for Windows/Android machines, and VoiceOver is popular for Mac/iOS.

I recommend testing your site via tab navigation and as many of the assistive devices mentioned above. Not only does this build empathy for people who use those technologies, but it provides you with a deeper understanding of the structure of your webpage!

How to build a more accessible site

Okay, now time for business.

Create a semantic and intuitive DOM structure

This is probably the easiest way to make your site more accessible, from the beginning. When deciding on which HTML element to use for a section of a page, consider the meaning of the element you are adding and the information it is trying to convey. If that meaning/information corresponds with a sementic HTML element, use that instead of a more generic tag (e.g. <div> or <span>).

This also applies to heading elements, which are often used by screenreaders to create a skeleton overview of a site and skip between sections. Rather than thinking about heading elements as aesthetic, think of them as providing context and structure that points to important content. Roughly:

<h1> Only one per page that declares its title.
<h2> Reflects main section headings and/or important, landmark pieces of information that provide context
<h3> Smaller section headings
<h4> etc

It's also not a bad idea to create screenreader-only headings if a section doesn't have a clear place for displaying a text heading. For example, a big photo section that showcases some recent work might want to include a screenreader-only heading that reads <h3>: Our Recent Work so that those who are visually impaired will understand the significance of the section.

See the section on "hiding things" for more information on how to implement screenreader-only headings and other items.

Evaluate the basics via browser extension

There are several high quality accessibility-focused browser extensions out there. They are very helpful, but by no means the be-all-end-all. I like to think of them as useful tools for evaluating and some of the more measurable accessibility attributes:

  1. Wave (available on Firefox & Chrome)
  2. Axe (available on Chrome and native iOS/Android)
  3. Lighthouse (built into Chrome devtools)

It's a good idea to run these extensions every once and awhile just to make sure you're on track and haven't diverged too much from convention.

Keyboard navigation vs. screenreader behavior

What is picked up by various screenreader technology is not necessarily the same as what is picked up by keyboard users, and what elements are tabbable (i.e. can be picked up by a user using the tab key to navigate through the page) are should not necessarily be focusable.

One easy rule: "tabbable" behavior should only apply to elements that are interactive - buttons, links, dropdowns - and the browser should make these elements tabbable by default. If using a <div> or <span> to create an interactive element, you should be using tabindex="0".

The ARIA specification is your friend

Accessible Rich Internet Applications (Aria) supplements HTML so that interactions and widgets commonly used in applications can be passed to assistive technologies when there is not otherwise a mechanism. For example, ARIA enables accessible navigation landmarks in HTML4, JavaScript widgets, form hints and error messages, live content updates, and more - Mozilla - using Aria

However, the ARIA specification is expansive. Here are some of the specific attributes I found useful:

  • aria-expanded: provides info to user about if an element is in an expanded or collapsed state
  • aria-hidden: indicates that the element and all of its descendants are not visible or perceivable to any user
  • aria-label: use in cases where some additional text might be helpful if the purpose for something isn't to someone visually impaired, i.e. a close button
    • aria-labelledby: should be used if there is a visible text label
  • aria-live: helps screenreader read out dynamic content changes. Usually aria-live="polite" is used, which speaks out those changes when there is a natural pause (instead of interrupting).
    • aria-live should live on the element that you expect/want the changes to be announced on. For example, a dynamically changing title:
<h3 className="screenreader-only" aria-live="polite">Slide {{ currentIndex + 1 }} of {{ images.length }}</h3>
  • aria-role: helpful for when you are using something differently than how its html attribute would indicate.
    • Ex. using a styled div with a link should use role="button"

Hiding things

One should try to default to using as many native DOM elements as possible and err towards the side of making visible, screenreader, and keyboard experiences as similar and high quality as possible. But sometimes that's not possible, and when extra information can be confusing to certain types of users, hiding things can be helpful.

Here's a great article by Paciello group on HTML hiding behaviors.

hidden, display:none; and visibility: hidden; will hide things from all users. If you want to add a specific element only for screenreaders, use a screenreader-only CSS class. Here's an example:

.screenreader_only {
  clip-path: inset(100%);
  clip: rect(1px 1px 1px 1px); /* IE 6/7 */
  clip: rect(1px, 1px, 1px, 1px);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap; /* added line */
  width: 1px;

Design considerations

I'm not a designer, and maybe neither are you, but here are some good things to keep in mind!

  • changes should not be flashing quickly (this can be confusing for people with cognitive disabilities)
  • notify users if you are changing the DOM on the fly. For example, if your nav has a dropdown, notify assistive devices via aria-live or aria-expanded (see last section for more on the aria specification)
  • try to avoid autoplay; if you do use some sort of autoplay behavior provide a way for users to pause/play or exit

play, for example -- can be a headache for users with assistive devices.

  • Color contrast and color dependence (for people who are low visibility or colorblind) is a common and relatively easy accessibility-related consideration to include in the design phase. 18F has a good guide for the specifics on contrast and dependence.

Thanks, a11y

Thanks for caring about accessibility! At the end of the day, making a site or web app more accessible means making it better for everyone to use :)

Additional reading/resources