Web Accessibility

This page contains excerpts from the Web Accessibility course from Udacity and Accessibility Web Fundamentals page from Google.

This video was created by Udacity as part of the Web Accessibility course

Accessibility is the experience of users who might be outside the narrow range of the "typical" user, who might access or interact with things differently than you expect. Specifically, it concerns users who are experiencing some type of impairment or disability — and bear in mind that that experience might be non-physical or temporary.

Focus

This video was created by Udacity as part of the Web Accessibility course

Focus determines where keyboard events go in the page at any given moment. For instance, if you focus a text input field and begin typing, the input field receives the keyboard events and displays the characters you type. While it has focus, it will also receive pasted input from the clipboard.

DOM Order

This video was created by Udacity as part of the Web Accessibility course

DOM Order, or the order in which elements are laid inside the HTML page, can affect the focus. Native elements are automatically inserted into the tab order based on their position in the DOM. However, it's important to note that, using CSS, it's possible to have things exist in one order in the DOM but appear in a different order on screen.

Offscreen Content

This video was created by Udacity as part of the Web Accessibility course

When you have elements that receive focus when they're off screen, it can seem as if the focus is disappearing and reappearing as the user tabs through the page — clearly an undesirable effect. Ideally, we should prevent the panel from gaining focus when it's off screen, and only allow it to be focused when the user can interact with it.

You should make sure you are appropriately hiding offscreen content with display: none or visibility: hidden.

Using Tabindex

This video was created by Udacity as part of the Web Accessibility course

The default tab order provided by the DOM position of native elements is convenient, but there are times when you'll want to modify the tab order, and physically moving elements in the HTML isn't always an optimal, or even a feasible, solution. For these cases, using the tabindex can explicitly set an element's tab position.

Managing Focus

This video was created by Udacity as part of the Web Accessibility course

This video was created by Udacity as part of the Web Accessibility course

Keyboard Traps

This video was created by Udacity as part of the Web Accessibility course

Sometimes when you're managing focus you can get into a situation you can't get out of. Consider an autocomplete widget that tries to manage focus and captures the tab behavior, but prevents the user from leaving it until it's complete. This is called a keyboard trap, and it can be very frustrating for the user.

Semantics

Assistive Technology

This video was created by Udacity as part of the Web Accessibility course

Assistive technology is an umbrella term for devices, software, and tools that help any person with a disability complete a task.

The line between assistive technology and technology in general is blurry; after all, all technology is meant to assist people with some task or another. And technologies can often move into and out of the "assistive" category.

Affordances

This video was created by Udacity as part of the Web Accessibility course

When we use a man-made tool or device, we typically look to its form and design to give us an idea of what it does and how it works. An affordance is any object that offers, or affords, its user the opportunity to perform an action. The better the affordance is designed, the more obvious or intuitive its use.

The Accessibility Tree

This video was created by Udacity as part of the Web Accessibility course

When a browser presents a page to a screen reader, it takes the DOM tree and modifies it into a form that is useful to assistive technology. We refer to this modified tree as the Accessibility Tree.

The accessibility tree is what most assistive technologies interact with. The flow goes something like this.

  1. An application (the browser or other app) exposes a semantic version of its UI to assistive technology via an API.
  2. The assistive technology may use the information it reads via the API to create an alternative user interface presentation for the user. For example, a screen reader creates an interface in which the user hears a spoken representation of the app.
  3. The assistive technology may also allow the user to interact with the app in a different way. For example, most screen readers provide hooks to allow a user to easily simulate a mouse click or finger tap.
  4. The assistive technology relays the user intent (such as "click") back to the app via the accessibility API. The app then has the responsibility to interpret the action appropriately in the context of the original UI.

Our job as web developers is to be aware that this is going on, and to develop web pages that take advantage of this process to create an accessible experience for our users.

Writing Semantic HTML

This video was created by Udacity as part of the Web Accessibility course

A browser can transform the DOM tree into an accessibility tree because much of the DOM has implicit semantic meaning. That is, the DOM uses native HTML elements that are recognized by browsers and work predictably on a variety of platforms. Accessibility for native HTML elements such as links or buttons is thus handled automatically. We can take advantage of that built-in accessibility by writing HTML that expresses the semantics of our page elements.

When we don't use an actual button element, the screen reader has no way to know what it has landed on. Also, we would have to do the extra work of adding tabindex to make it usable to keyboard-only users because, as it is coded now, it can only be used with a mouse.

Earlier we noted that screen readers will announce an element's role, name, state, and value. By using the right semantic element, role, state, and value are covered, but we must also ensure that we make an element's name discoverable.

Broadly, there are two types of names:

  • Visible labels, which are used by all users to associate meaning with an element, and
  • Text alternatives, which are only used when there is no need for a visual label.

Visible Labels

For text-level elements, we don't need to do anything, because by definition it will have some text content. However, for input or control elements, and visual content like images, we need to make sure that we specify a name.

One way to do that is to follow their recommendation that "Form inputs have associated text labels." There are two ways to associate a label with a form element, such as a checkbox. Either of the methods causes the label text to also become a click target for the checkbox, which is also helpful for mouse or touchscreen users. To associate a label with an element, either

  • Place the input element inside a label element
  • Use the label's for attribute and refer to the element's id

Text Alternative

This video was created by Udacity as part of the Web Accessibility course

Images are an important component of most web pages, and are of course a particular sticking point for low-vision users. We must consider the role an image plays in a page to work out what type of text alternative it should have.

A couple of comments about alt:

  • The alt allows you to specify a simple string to be used any time the image isn't available, such as when the image fails to load, or is accessed by web crawling bot, or is encountered by a screen reader.
  • The alt differs from title, or any type of caption, in that it is only used if the image is not available.

It might be tempting to give it a simpler text alternative of "home" or "main page", but that does a disservice to both low-vision and sighted users.

On the other hand, it's not always useful to describe an image, especially if will produce redundant information. In this case you can just use an empty alt attribute, and the screen reader will skip the image altogether.

In a simple page with lots of controls but not much content, it's easy to scan the page to find what you need. But on a content-heavy page, such as a Wikipedia entry or a news aggregator, it's not practical to read through everything from the top down; you need a way to efficiently navigate through the content.

Screen reader users often rely on a list of headings to locate information. Most screen readers have easy ways to isolate and scan a list of page headings, an important feature called the rotor. Because screen readers interact with the accessibility tree, and the accessibility tree is based on the DOM tree, the order a screen reader perceives is thus directly based on the DOM order. This means that an appropriate heading structure is more important than ever.

In most well-structured pages, the heading levels are nested to indicate parent-child relationships among content blocks.

ARIA

What is ARIA

This video was created by Udacity as part of the Web Accessibility course

Native HTML elements give you focus, keyboard support, and built-in semantics, but there are times when a simple layout and native HTML won't do the job. For example, currently there's no standardized HTML element for a very common UI construct, the pop-up menu. Nor is there an HTML element that provides a semantic characteristic such as "the user needs to know about this as soon as possible". This is where ARIA comes in.

The Web Accessibility Initiative's Accessible Rich Internet Applications specification (WAI-ARIA, or just ARIA) is good for bridging areas with accessibility issues that can't be managed with native HTML. It works by allowing you to specify attributes that modify the way an element is translated into the accessibility tree.

<li tabindex="0" class="checkbox" checked>
  Receive promotional offers
</li>

While this works fine for sighted users, a screen reader will give no indication that the element is meant to be a checkbox, so low-vision users may miss the element entirely.

Using ARIA attributes, however, we can give the element the missing information so the screen reader can properly interpret it. Here, we've added the role and aria-checked attributes to explicitly identify the element as a checkbox and to specify that it is checked by default. The list item will now be added to the accessibility tree and a screen reader will correctly report it as a checkbox.

<li tabindex="0" class="checkbox" role="checkbox" checked aria-checked="true">
  Receive promotional offers
</li>

ARIA works by changing and augmenting the standard DOM accessibility tree.

Although ARIA allows us to subtly (or even radically) modify the accessibility tree for any element on the page, that is the only thing it changes. ARIA doesn't augment any of the element's inherent behavior; it won't make the element focusable or give it keyboard event listeners. That is still part of our development task.

It's important to understand that there is no need to redefine default semantics. Regardless of its use, a standard HTML <input type="checkbox"> element doesn't need an additional role="checkbox" ARIA attribute to be correctly announced.

It's also worth noting that certain HTML elements have restrictions on what ARIA roles and attributes can be used on them. For example, a standard <input type="text"> element may not have any additional role/attribute applied to it.

Why Use ARIA

This video was created by Udacity as part of the Web Accessibility course

As you saw with the checkbox example, ARIA can modify existing element semantics or add semantics to elements where no native semantics exist. It can also express semantic patterns that don't exist at all in HTML, like a menu or a tab panel. Often, ARIA lets us create widget-type elements that wouldn't be possible with plain HTML.

For example, ARIA can add extra label and description text that is only exposed to assistive technology APIs.

<button aria-label="screen reader only label"></button>

ARIA can express semantic relationships between elements that extend the standard parent/child connection, such as a custom scrollbar that controls a specific region.

<div role="scrollbar" aria-controls="main"></div>
<div id="main">
. . .
</div>

And ARIA can make parts of the page "live", so they immediately inform assistive technology when they change.

<div aria-live="true">
  <span>GOOG: $400</span>
</div>

One of the core aspects of the ARIA system is its collection of roles. A role in accessibility terms amounts to a shorthand indicator for a particular UI pattern. ARIA provides a vocabulary of patterns we can use via the role attribute on any HTML element.

When we applied role="checkbox" in the previous example, we were telling assistive technology that the element should follow the "checkbox" pattern. That is, we're guaranteeing that it will have a checked state (either checked or not checked), and that the state may be toggled using the mouse or the spacebar, just like a standard HTML checkbox element.

In fact, because keyboard interactions feature so prominently in screen reader usage, it's very important to make sure that, when creating a custom widget, the role attribute is always applied in the same place as the tabindex attribute; this ensures that keyboard events go to the right place and that when focus lands on an element its role is conveyed accurately.

ARIA Roles

This video was created by Udacity as part of the Web Accessibility course

ARIA Labels

This video was created by Udacity as part of the Web Accessibility course

ARIA provides several mechanisms for adding labels and descriptions to elements. In fact, ARIA is the only way to add accessible help or description text. Let's look at the properties ARIA uses to create accessible labels.

aria-label

The aria-label allows us to specify a string to be used as the accessible label. This overrides any other native labeling mechanism, such as a label element — for example, if a button has both text content and an aria-label, only the aria-label value will be used.

You might use an aria-label attribute when you have some kind of visual indication of an element's purpose, such as a button that uses a graphic instead of text, but still need to clarify that purpose for anyone who cannot access the visual indication, such as a button that uses only an image to indicate its purpose.

aria-labelledby

The aria-labelledby allows us to specify the ID of another element in the DOM as an element's label.

This is much like using a label element, with some key differences.

  1. The aria-labelledby may be used on any element, not just labelable elements.
  2. While a label element refers to the thing it labels, the relationship is reversed in the the case of aria-labelledby — the thing being labeled refers to the thing that labels it.
  3. Only one label element may be associated with a labelable element, but aria-labelledby can take a list of IDREFs to compose a label from multiple elements. The label will be concatenated in the order that the IDREFs are given.
  4. You can use aria-labelledby to refer to elements that are hidden and would otherwise not be in the accessibility tree. For example, you could add a hidden span next to an element you want to label, and refer to that with aria-labelledby.
  5. However, since ARIA only affects the accessibility tree, aria-labelledby does not give you the familiar label-clicking behavior you get from using a label element.

Importantly, aria-labelledby overrides all other name sources for an element. So, for example, if an element has both an aria-labelledby and an aria-label, or an aria-labelledby and a native HTML label, the aria-labelledby label always takes precedence.

ARIA Relationships

This video was created by Udacity as part of the Web Accessibility course

The aria-labelledby is an example of a relationship attribute. A relationship attribute creates a semantic relationship between elements on the page regardless of their DOM relationship. In the case of aria-labelledby, that relationship is "this element is labelled by that element".

The ARIA specification lists eight relationship attributes. Six of these, aria-activedescendant, aria-controls, aria-describedby, aria-labelledby, and aria-owns, take a reference to one or more elements to create a new link between elements on the page. The difference in each case is what that link means and how it is presented to users.

aria-owns

The aria-owns is one of the most widely used ARIA relationships. This attribute allows us to tell assistive technology that an element that is separate in the DOM should be treated as a child of the current element, or to rearrange existing child elements into a different order. For example, if a pop-up sub-menu is visually positioned near its parent menu, but cannot be a DOM child of its parent because it would affect the visual presentation, you can use aria-owns to present the sub-menu as a child of the parent menu to a screen reader.

aria-activedescendant

The aria-activedescendant plays a related role. Just as the active element of a page is the one that has focus, setting the active descendant of an element allows us to tell assistive technology that an element should be presented to the user as the focused element when its parent actually has the focus. For example, in a listbox, you might want to leave page focus on the listbox container, but keep its aria-activedescendant attribute updated to the currently selected list item. This makes the currently selected item appear to assistive technology as if it is the focused item.

aria-describedby

The aria-describedby provides an accessible description in the same way that aria-labelledby provides a label. Like aria-labelledby, aria-describedby may reference elements that are otherwise not visible, whether hidden from the DOM, or hidden from assistive technology users. This is a useful technique when there is some extra explanatory text that a user might need, whether it applies only to users of assistive technology or all users.

A common example is a password input field that is accompanied by some descriptive text explaining the minimum password requirements. Unlike a label, this description may or may not ever be presented to the user; they may have a choice of whether to access it, or it may come after all the other information, or it may be pre-empted by something else. For example, if the user is entering information, their input will be echoed back and may interrupt the element's description. Thus, a description is a great way to communicate supplementary, but not essential, information; it won't get in the way of more critical information such as the element's role.

aria-posinset & aria-setsize

The remaining relationship attributes are a little different, and work together. The aria-posinset ("position in set") and the aria-setsize ("size of set") are about defining a relationship between sibling elements in a set, such as a list.

When the size of a set cannot be determined by the elements present in the DOM — such as when lazy rendering is used to avoid having all of a large list in the DOM at once — aria-setsize can specify the actual set size, and aria-posinset can specify the element's position in the set. For example, in a set that might contain 1000 elements, you could say that a particular element has an aria-posinset of 857 even though it appears first in the DOM, and then use dynamic HTML techniques to ensure that the user can explore the full list on demand.

Hidden Content

This video was created by Udacity as part of the Web Accessibility course

aria-hidden

Another important technique in fine-tuning the experience for assistive technology users involves ensuring that only relevant parts of the page are exposed to assistive technology. There are several ways to ensure that a section of the DOM does not get exposed to accessibility APIs.

First, anything that is explicitly hidden from the DOM will also not be included in the accessibility tree. So anything that has a CSS style of visibility: hidden or display: none or uses the HTML5 hidden attribute will also be hidden from assistive technology users.

However, an element that is not visually rendered but not explicitly hidden is still included in the accessibility tree. One common technique is to include "screen reader only text" in an element that is absolute positioned offscreen.

.sr-only {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

Also, as we have seen, it's possible to provide screen reader only text via an aria-label, aria-labelledby, or aria-describedby attribute referencing an element that is otherwise hidden.

See this WebAIM article on Techniques for hiding text for more information on creating "screen reader only" text.

Finally, ARIA provides a mechanism for excluding content from assistive technology that is not visually hidden, using the aria-hidden attribute. Applying this attribute to an element effectively removes it and all of its descendants from the accessibility tree. The only exceptions are elements referred to by an aria-labelledby or aria-describedby attribute.

<div class="deck">
  <div class="slide" aria-hidden="true">
    Sales Targets
  </div>
  <div class="slide">
    Quarterly Sales
  </div>
  <div class="slide" aria-hidden="true">
    Action Items
  </div>
</div>

For example, you might use aria-hidden if you're creating some modal UI that blocks access to the main page. In this case, a sighted user might see some kind of semi-transparent overlay indicating that most of the page can't currently be used, but a screen reader user may still be able to explore to the other parts of the page. In this case, as well as creating the keyboard trap explained earlier, you need to make sure that the parts of the page that are currently out of scope are aria-hidden as well.

Styling

Focus

This video was created by Udacity as part of the Web Accessibility course

Generally, any time we focus an element, we rely on the built-in browser focus ring (the CSS outline property) to style the element. The focus ring is handy because, without it, it's impossible for a keyboard user to tell which element has the focus. The WebAIM checklist makes a point of this, requiring that "It is visually apparent which page element has the current keyboard focus (i.e., as you tab through the page, you can see where you are)."

However, sometimes the focus ring can look distorted or it may just not fit in with your page design. Some developers remove this style altogether by setting the element's outline to 0 or none. But without a focus indicator, how is a keyboard user supposed to know which item they're interacting with?

Warning

Never set outline to 0 or none without providing a focus alternative!

You might be familiar with adding hover states to your controls using the CSS :hover pseudo-class. For example, you might use :hover on a link element to change its color or background when the mouse is over it. Similar to :hover, you can use the :focus pseudo-class to target an element when it has focus.

/* At a minimum you can add a focus style that matches your hover style */
:hover, :focus {
  background: #c0ffee;
}

An alternative solution to the problem of removing the focus ring is to give your element the same hover and focus styles, which solves the "where's-the-focus?" problem for keyboard users. As usual, improving the accessibility experience improves everyone's experience.

Styling with ARIA

This video was created by Udacity as part of the Web Accessibility course

A useful technique to employ here is to remove the class altogether, and just use the ARIA attributes to style the element. Now you can update the CSS selector for the pressed state of the button from this

.toggle.pressed { ... }

to this.

.toggle[aria-pressed="true"] { ... }

This creates both a logical and a semantic relationship between the ARIA state and the element's appearance, and cuts down on extra code as well.

Responsive Design

This video was created by Udacity as part of the Web Accessibility course

We know that it's a good idea to design responsively to provide the best multi-device experience, but responsive design also yields a win for accessibility.

In fact, just by designing responsively, we're meeting rule 1.4.4 of the WebAIM checklist, which states that a page "...should be readable and functional when the text size is doubled."

Going over all of responsive design is outside the scope of this guide, but here are a few important takeaways that will benefit your responsive experience and give your users better access to your content.

  • First, make sure you always use the proper viewport meta tag. <meta name="viewport" content="width=device-width, initial-scale=1.0"> Setting width=device-width will match the screen's width in device-independent pixels, and setting initial-scale=1 establishes a 1:1 relationship between CSS pixels and device-independent pixels. Doing this instructs the browser to fit your content to the screen size, so users don't just see a bunch of scrunched-up text.

Warning

When using the viewport meta tag, make sure you don't set maximum-scale=1 or set user-scaleable=no. Let users zoom if they need to!

  • Another technique to keep in mind is designing with a responsive grid. As you saw with the Udacity site, designing with a grid means your content will reflow when the page changes size. Often these layouts are produced using relative units like percents, ems, or rems instead of hard-coded pixel values. The advantage of doing it this way is that text and content can enlarge and force other items down the page. So the DOM order and the reading order remain the same, even if the layout changes because of magnification.
  • Also, consider using relative units like em or rem for things like text size, instead of pixel values. Some browsers support resizing text only in user preferences, and if you're using a pixel value for text, this setting will not affect your copy. If, however, you've used relative units throughout, then the site copy will update to reflect the user's preference.
  • Finally, when your design is displayed on a mobile device, you should ensure that interactive elements like buttons or links are large enough, and have enough space around them, to make them easy to press without accidentally overlapping onto other elements. This benefits all users, but is especially helpful for anyone with a motor impairment.