Thursday, May 12, 2016

How to Make Accessible Web Components — a Brief Guide

This article was peer reviewed by Mallory van Achterberg. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

In a previous article I demonstrated how to create a multiselect web component. In the comments section of that article, readers touched on the very important subject of web component accessibility. Undoubtedly, for today's web it's vital to be accessible, so let's talk about what accessibility stands for and see (by means of a real-world example) how to make a web component more accessible.

The code in this article will build upon the code from my previous article. You can grab a copy of it from our GitHub repo, or check out a demo of the accessible component at the end of the article.

What Does Web Component Accessibility Entail?

When talking about the accessibility of a component we usually consider the following aspects:

[author_more]

  1. Markup semantics
  2. Keyboard support
  3. Visual accessibility

Let's discuss each aspect in a little more detail.

Markup Semantics

I'm sure you've heard about screen readers. A screen reader is a piece of assistive software that allows blind or visually impaired people to use applications by reading aloud information displayed on the screen. There are many screen readers out there, among them NVDA and JAWS for Windows, ChromeVox for Chrome and VoiceOver for OS X.

When an element receives focus, the screen reader offers information about it to the user. Thus when an HTML <input type="text"> is focused the user knows from the screen reader that they are dealing with text field (and can input something). But if the element is just a bare <div>, the screen reader has nothing to say about it.

To solve this issue we can use WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) to add special ARIA attributes to extend the semantics of the component markup. These additional semantics help assistive technologies to identify properties, relationships, and states in your user interfaces. The practical guidelines for using ARIA can be found here: WAI-ARIA Authoring Practices, alternatively (for a quick refresher) you could read our Introduction to WAI-ARIA.

Keyboard Support

The goal is to make it possible to interact with a component using only the keyboard. WAI-ARIA defines behavior and the keyboard interactions for many UI controls. To know which keys should be supported by which component, find the description of your component or a similar one in the specification and use that. For instance, the multiselect is similar to the combobox.

Even with keyboard accessibility in place, it's good practice is to let users know which keys/key combos to use to interact with the component (for example by providing some instructions in the application) since this might not be obvious.

Visual Accessibility

Here we are talking about accessibility aspects related to the component's appearance. Ensure that you can answer 'yes' to the following questions:

  • Are the elements and text big enough to clearly see them?
  • Does your component look as expected in high contrast mode?
  • Is it possible to use your component without colors?

Remember, not all visually impaired users are legally blind. There are many users out there who (for example) have low vision or color blindness.

Making the Multiselect Web Component Accessible

Now we're going to make the multiselect more accessible using all of the techniques outlined above. Specifically, we're going to:

  • extend the markup semantics
  • add keyboard support
  • validate its visual accessibility

Don't forget, you can view the demo of the component at the end of the article, or download the code from our GitHub repo. All of the code snippets can be found in the multiselect.html file.

Extending Markup Semantics

The accessibility rule of thumb is to use native HTML elements over custom ones. This means, if you can use a native HTML control with built-in accessibility, do so. Add ARIA attributes only if you really need to create a custom component. If you'd like to find out more about this, read Avoiding Redundancy with WAI-ARIA in HTML Pages.

In our case the multiselect is a custom component, so we need to add ARIA attributes. First, let's find a component similar to the multiselect in the ARIA specification. After a little research, it appears that the combobox looks and behaves similarly. Great, now let's see which ARIA attributes we need to add according to the combobox description.

From guidelines we can see that we need to add the following roles:

  1. role="combobox" to the root element of the component
  2. role="listbox" to the list of items in the popup
  3. role="option" to each item of the dropdown list

The aria state attributes to be added:

  1. aria-expanded="true/false" to the root element to indicate whether the component is opened or closed
  2. aria-selected="true/false" to each item of the dropdown list to indicate selected state

The roles combobox and listbox can be added directly to the markup of the component:

<div class="multiselect" role="combobox">
  <div class="multiselect-field"></div>
  <div class="multiselect-popup">
    <ul class="multiselect-list" role="listbox">
      <content select="li"></content>
    </ul>
  </div>
</div>

To add the role option to each item of the list we loop over items in the refreshItems method. This new method is called when the component is rendered:

multiselectPrototype.render = function() {
  this.attachHandlers();
  this.refreshField();
  this.refreshItems();
};

multiselectPrototype.refreshItems = function() {
  var itemElements = this.itemElements();

  for(var i = 0; i < itemElements.length; i++) {
    var itemElement = itemElements[i];

  // set role and aria-selected property of an item
    itemElement.setAttribute("role", "option");
    itemElement.setAttribute("aria-selected", itemElement.hasAttribute("selected"));
  }
};

multiselectPrototype.itemElements = function() {
  return this.querySelectorAll('li');
};

The aria-expanded attribute can be added to the control in the togglePopup method which (as the name suggests) is responsible for showing and hiding the popup:

multiselectPrototype.togglePopup = function(show) {
  this._isOpened = show;
  this._popup.style.display = show ? 'block' : 'none';

  // set aria-expanded property
  this._control.setAttribute("aria-expanded", show);
};

We also initialize the aria-selected property of items depending on their selected attribute. The aria-selected property should be maintained to reflect the current item's selected state. We can do that in selectItem and unselectItem methods:

multiselectPrototype.selectItem = function(item) {
  if(!item.hasAttribute('selected')) {
    // set aria-selected property of selected item
    item.setAttribute('aria-selected', true);

    item.setAttribute('selected', 'selected');
    this.fireChangeEvent();
    this.refreshField();
  }

  this.close();
};

multiselectPrototype.unselectItem = function(item) {
  // set aria-selected property of unselected item
  item.setAttribute('aria-selected', false);

  item.removeAttribute('selected');
  this.fireChangeEvent();
  this.refreshField();
};

And that's it, the ARIA properties have been added. The next step is keyboard support.

Continue reading %How to Make Accessible Web Components — a Brief Guide%


by Artem Tabalin via SitePoint

No comments:

Post a Comment