Introduction

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. Let's look at an example.

In the following snippet, we use a list item as a kind of custom checkbox. The CSS "checkbox" class gives the element the required visual characteristics.

  • Receive promotional offers
  • 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.

    
    

    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 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 element may not have any additional role/attribute applied to it.

    What can ARIA do?

    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.
    
    
    • ARIA can express semantic relationships between elements that extend the standard parent/child connection, such as a custom scrollbar that controls a specific region.
    . . .
    • And ARIA can make parts of the page "live", so they immediately inform assistive technology when they change.
    GOOG: $400

    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.

    The ARIA spec describes a taxonomy of possible values for the role attribute and associated ARIA attributes that may be used in conjunction with those roles. This is the best source of definitive information about how the ARIA roles and attributes work together and how they can be used in a way that is supported by browsers and assistive technologies.

    Labels

    aria-label

    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

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

    Drink options
    
    . . .

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

    1. 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.

    Relationships

    aria-owns

    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.

    New

    aria-activedescendant

    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.

    ...
    Item 5
    Item 6
    Item 7
    Item 8
    ...

    aria-describedby

    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.

    
    
    
    Password must be at least 12 characters

    aria-posinset & aria-setsize

    The remaining relationship attributes are a little different, and work together. aria-posinset ("position in set") and 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.

    Item 857
    Item 858

    Hiding and Updating Content

    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.

    Quarterly Sales

    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.

    Now that you understand the basics of ARIA, how it plays with native HTML semantics, and how it can be used to perform fairly major surgery on the accessibility tree as well as changing the semantics of a single element, let's look at how we can use it to convey time-sensitive information.

    aria-live

    aria-live lets developers mark a part of the page as "live" in the sense that updates should be communicated to users immediately regardless of the page position, rather than if they just happen to explore that part of the page. When an element has an aria-live attribute, the part of the page containing it and its descendants is called a live region.

    Could not connect!

    For example, a live region might be a status message that appears as a result of a user action. If the message is important enough to grab a sighted user's attention, it is important enough to direct an assistive technology user's attention to it by setting its aria-live attribute. Compare this plain div

    Your message has been sent.

    with its "live" counterpart.

    Your message has been sent.

    aria-live has three allowable values: polite, assertive, and off.

    • aria-live="polite" tells assistive technology to alert the user to this change when it has finished whatever it is currently doing. It's great to use if something is important but not urgent, and accounts for the majority of aria-live use.
    • aria-live="assertive" tells assistive technology to interrupt whatever it's doing and alert the user to this change immediately. This is only for important and urgent updates, such as a status message like "There has been a server error and your changes are not saved; please refresh the page", or updates to an input field as a direct result of a user action, such as buttons on a stepper widget.
    • aria-live="off" tells assistive technology to temporarly suspend aria-live interruptions.

    There are some tricks to making sure your live regions work correctly.

    First, your aria-live region should probably be set in the initial page load. This is not a hard-and-fast rule, but if you're having difficulty with an aria-live region, this might be the issue.

    Second, different screen readers react differently to different types of changes. For example, it's possible to trigger an alert on some screen readers by toggling a descendant element's hidden style from true to false.

    Other attributes that work with aria-live help you fine-tune what is communicated to the user when the live region changes.

    aria-atomic indicates whether the entire region should be considered as a whole when communicating updates. For example, if a date widget consisting of a day, month, and year has aria-live=true and aria-atomic=true, and the user uses a stepper control to change the value of just the month, the full contents of the date widget would be read out again. aria-atomic's value may be true or false (the default).

    aria-relevant indicates what types of changes should be presented to the user. There are some options that may be used separately or as a token list.

    • additions, meaning that any element being added to the live region is significant. For example, appending a span to an existing log of status messages would mean that the span would be announced to the user (assuming that aria-atomic was false).
    • text, meaning that text content being added to any descendant node is relevant. For example, modifying a custom text field's textContent property would read the modified text to the user.
    • removals, meaning that the removal of any text or descendant nodes should be conveyed to the user.
    • all, meaning that all changes are relevant. However, the default value for aria-relevant is additions text, meaning that if you don't specify aria-relevant it will update the user for any addition to the element, which is what you are most likely to want.

    Finally, aria-busy lets you notify assistive technology that it should temporarily ignore changes to an element, such as when things are loading. Once everything is in place, aria-busy should be set to false to normalize the reader's operation.

    References

    All documentation was referenced by Google Developers in their Web Fundamentals section. For even more information, visit W3C's site on its official use.