As accessibility-minded developers working on accessibility-minded teams, we strive to design and build inclusive applications that yield a pleasant experience for all users. However, despite our best efforts we may make mistakes and implement features in a sub-optimal way, or worse, discover that some users cannot use those features at all. Fortunately, in recent years browsers have introduced tools that help debug some of these issues. Here we will focus on the built-in accessibility inspectors that allow developers to navigate the accessibility tree that browsers present to assistive technologies.

Accessibility Tree

Since an assistive technology (AT) is expected to provide a unified experience across multiple desktop applications, it does not interact directly with the browser but rather through an accessibility API that sits between the AT and the browser. As such, when the browser reads a page’s HTML, it will not only generate the DOM tree but if an AT is running the browser will also generate an accessibility tree that represents the DOM structure’s computed accessibility properties. ATs then read (and perhaps transform) this accessibility tree to generate their own user experience.

While most of the DOM tree will exist in some form in the accessibility tree, the browser can optimize the accessibility tree by removing hidden elements or those it determines provide no useful meaning to the user (e.g., presentation-only wrapper nodes). Further, the exact structure of the accessibility tree is implementation-specific; for example, browsers may use different node names for identical nodes, decorate nodes with properties not used by other browsers, or attempt to correct poorly-constructed markup. However, there are commonalities that are required for compatibility with the underlying accessibility API, including an element’s:

  • role, which helps inform users how they can expect to interact with the element. For example, if an element’s role is listed as “checkbox” or “checkbutton” (depending on the browser), the user knows the element can receive focus and get selected or deselected.
  • optional name or label, which helps define the purpose of the element. For example, if the element is a button, its text content will get used as its name. Alternatively, if it contains an aria-label attribute, its name will be the value of that attribute; if it contains an aria-labelledby attribute, then its name will be the computed name of the element with the ID specified by aria-labelledby.
  • various states, such as whether the element is focusable, disabled, selected, etc.

Accessibility Inspectors

Now that we have a better understanding of how browsers represent the document structure to assistive technologies, we can discuss the tools that browsers provide developers for interacting with those structures and determining the computed accessibility properties for any given DOM node. At present, accessibility inspectors are provided in some form by:

  • Firefox
  • Chrome, Chromium Edge, and Brave
  • Safari

In the following sections, we will examine each availability inspector in turn using an example breadcrumb implementation using the HTML below. Note that no styling has been applied and that the list HTML is deliberately malformed in order to demonstrate how it affects the accessibility tree in each browser:

<!DOCTYPE html>
<html lang="en">
    <head>
   	 <meta charset="utf-8">
   	 <title>Accessibility Inspector Demo</title>
    </head>
    <body>
   	 <nav aria-label="breadcrumb">
   		 <ol>
   			 <div>
   				 <li><a href="/step-one">Step One</a></li>
   				 <li><a aria-current="step" href="/step-two">Step Two</a></li>
   				 <li><a href="/step-three">Step Three</a></li>
   			 </div>
   		 </ol>
   	 </nav>
    </body>
</html>

Firefox

Of the listed browser platforms, only Firefox allows developers to navigate the entire accessibility tree as they would the DOM tree. Firefox’s inspector can be found in the “Accessibility” tab of its developer tools. This tab should be displayed, but if not then it will need to be enabled manually. To do so, open the “Customize Developer Tools and Get Help” menu (displayed as an ellipsis button next to the “Close” button in the main dev tools toolbar) and then navigate to “Settings”. The accessibility tab can be enabled by checking the “Accessibility” checkbox in the “Default Developer Tools” section.

In order to optimize performance, browsers will not generate an accessibility tree unless needed. So once the “Accessibility” tab is enabled and displayed, the accessibility features need to be enabled via the “Turn On Accessibility Features” button unless an assistive technology is already running. With the accessibility features enabled, the accessibility tree is displayed in the tab contents, and the accessibility properties of any node get revealed by 1) expanding nodes in the tree individually, 2) using the “Pick accessible object from the page” button (the first button in the toolbar when the “Accessibility” tab is selected) or 3) right-clicking any element on the page and choosing “Inspect Accessibility Properties” from the context menu.

Returning to breadcrumb example above, Firefox generates the following accessibility tree:

Firefox accessibility inspector showing the breadcrumb example

Even with our small example, there is much to explore. The main tab content area displays each node’s role and name, but there is also a “Properties” accordion pane that contains additional information such as the node’s various states (e.g., “focusable” and “enabled”). In order to understand how this helps us improve the user experience, notice that the structure of the breadcrumb list appears wrong. Specifically, after the list node we would expect there to be listitem nodes for each of the three items in the breadcrumb. Instead, there is a single section followed by three text container nodes. This is due to the <div> that wraps the three <li> tags, and the resulting accessibility tree structure indicates that assistive technologies may not present this to users in the way we expect. In fact, VoiceOver on macOS does not treat this example as a list of three items, but instead as a list of one item, so that navigating through the list results in the following reading:

list one item
link, Step One
link, Step Two
link, Step Three

To correct this, we need to remove the <div> around the three list items in order to restore the expected relationship between the list and its individual items:

Firefox accessibility inspector showing the same breadcrumb example but with corrected semantics

After removing the <div>, the accessibility tree displays the breadcrumb items as listitem nodes as expected, and VoiceOver now indicates that our list has three items, and also reads each step number:

list three items
text, 1 of 3
link, Step One
text, 2 of 3
link, Step Two
text, 3 of 3
link, Step Three

Chrome and Chromium Browsers

Rather than provide a separate, top-level tab for viewing the accessibility tree, the Chrome developer tools add a child “Accessibility” tab to the top-level “Elements” tab. While it is not possible to navigate the entire accessibility tree freely, Chrome’s tools still provide plenty of useful information:

Chrome accessibility inspector showing the breadcrumb example

In the above image, the <div> that wraps the breadcrumb’s list items is selected and its accessibility properties get displayed. In Firefox, this node was included in the accessibility tree, degrading the user experience. However, the “Computed Properties” for this same node in Chrome report, “Accessibility node not exposed. Element not interesting for accessibility.” If we then highlight one of the links in the breadcrumb, we can see in the “Accessibility Tree” accordion pane that the relationship between the list and the list item is preserved. Chrome recognizes that the <div> should not have been added around the list items and therefore ignores it.

Chrome accessibility inspector showing the accessibility tree and properties for a breadcrumb item link.

Of course, we cannot be certain what an AT will read to users until we test it ourselves. Navigating our page with VoiceOver enabled verifies that we interpreted the computed accessibility correctly:

list 3 items
1
link, Step One
2
link, Step Two
3
link, Step Three

Note that this simple example was chosen deliberately to demonstrate how browsers might modify the DOM tree when generating the accessibility tree. Since there is no guarantee that such behavior will be preserved in future releases or that all poorly-written markup will be optimized, we still must fix our code. After doing so, VoiceOver verifies that everything is read as expected:

list 3 items
1
link, Step One
2
link, Step Two
3
link, Step Three

Safari

As with Chrome, Safari includes the nodes’ accessibility properties in the top-level “Elements” tab. However, the available information is minimum compared to that provided by either Firefox or Chrome. To view a node’s accessibility properties, inspect the node in the “Elements” tab of the developer tools, select the “Nodes” child tab in the adjacent child pane, and then expand the “Accessibility” accordion pane:

Safari accessibility inspector showing the breadcrumb example

Safari’s inspector reports only a small number of properties for each node: its role, name (which it calls “label”), parent, children, ARIA properties, and basic states such as whether the node is disabled or focused. As is shown by the previous image, the accessibility properties for the <div> that wraps the list items include “Ignored: Yes”, indicating that Safari, like Chrome, has “fixed” the accessibility tree for AT users for this specific example. Before correcting our markup, we can prove this by listening to how VoiceOver reads our page (note that Safari also supports the aria-current attribute added to the second breadcrumb item):

list 3 items
1
link, Step One
2
current step, link, Step Two
3
link, Step Three

Conclusion

While there is no substitute for testing our applications with assistive technologies likes NVDA or VoiceOver, the growing suite of tools available to developers improves the likelihood that our web sites and applications will be inclusive of all users. Currently, Firefox is the only browser that allows the entire accessibility tree to be navigated and viewed in its entirety, although other browsers provide at least some useful information to debug problems encountered when testing with assistive technologies.

Do you need help improving the accessibility of your applications? Contact us to discuss how we can help you improve your applications and provide excellent experiences for all users.