Get started screen reader testing with screen readers and the accessibility tree
Tags: a11y, codenewbie, html, beginners
Published: 2021-01-25 01:48:30

---
title: Get started screen reader testing with screen readers and the accessibility tree
published: true
description: 
tags: #accessibility, #codenewbie, #html, #beginners
---

If you're getting started with web accessibility, you'll want to understand what exactly the results and end goal are to accessibility work. Accessibility work takes many forms such as making sure your design has good color contrast, has a consistent layout, works well with keyboard and mobile navigation, and is usable with tools like screen readers. All this work is ultimately toward your app being usable to as many people as possible.

In this tutorial, I'd like to zoom in on testing one of these aspects of accessibility: screen reader usability. Some people who might use screen readers, plus keyboard navigation are:

* Someone who is blind or visually impaired
* Someone who got their pupils dilated for an eye exam
* Someone who navigates the web best with audio
* Someone with motor impairment that causes difficulty using a mouse

We'll look at two technologies in this tutorial so you can see firsthand how your app works on a screen reader. They are the screen readers themselves, and the accessibility tree.

By the way, while I've read a lot about accessibility, I'm still fairly new to it. If you are experienced in it and know other great tools and techniques for manual accessibility testing, though, I would love to learn the tools you use, so you're more than welcome to share them in the comments!

## A poll made of divs

To show the effects of accessible coding techniques, let's start by writing code for an app that **isn't** accessible: a poll made of divs. First up, let's make the HTML:

```html
<div id="inaccessible-poll">
  <h1>Pick your favorite programminng language</h1>
  <div id="options">
    <div id="go-div" class="language"
      onclick="selectLanguage('go-div')">Go</div>
    <div id="javascript-div" class="language"
      onclick="selectLanguage('javascript-div')">JavaScript</div>
    <div id="ruby-div" class="language"
      onclick="selectLanguage('ruby-div')">Ruby</div>
  </div>
  <button>Vote</button>
</div>
```

Each div of class `language` will be like a button; you click on it to select the language you want, which is handled with the `selectLanguage` JavaScript function, that looks like this:

```javascript
var selectedLanguage = null;

function selectLanguage(language) {
  if (selectedLanguage != null && selectedLanguage != language) {
    document.getElementById(selectedLanguage).classList.remove('selected');
  }
  selectedLanguage = language;
  document.getElementById(selectedLanguage).classList.add('selected');
}
```

Finally, here's some CSS for styling the buttons, lighting them up in their programming lanugage's color when a user clicks on them:

```css
#options {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  column-gap: 20px;
  margin-bottom: 20px;
}

#go-div.selected {
  background-color: cyan;
}

#javascript-div.selected {
  background-color: #fff94a;
}

#ruby-div.selected {
  background-color: rgb(255, 21, 21);
}

.language {
  padding:       20px;
  border-radius: 20px;
  border-color:  black;
  border-style:  solid;
  text-align:    center;
  font-weight:   bolder;
  font-family:   sans-serif;
}

button {
  font-size: 24px;
  padding: 6px;
}
```

The final product looks like this:

![The webpage with three buttons for selecting your favorite programming language. JavaScript is selected and highlighted in yellow.](https://dev-to-uploads.s3.amazonaws.com/i/6n92ziud6gwny0u838wo.png)

However, if you're using a screen reader, this app isn't accessible. But don't take my word for it, let's try out this app using a screen reader!

## Testing our app with a screen reader

Let's start by setting up a screen reader to test our app.

If you use a Mac, go to `Settings > Accessibility (icon looks like a person on a blue background)`, then in the left bar under Vision, select **VoiceOver**, and check off the box **Enable VoiceOver**.

You can also find a tutorial on how to use it under the button "Open VoiceOver training".

![The accessibility section of the Mac settings, with VoiceOver selected](https://dev-to-uploads.s3.amazonaws.com/i/lel68nwmelia98w14ct4.png)

If you use Windows, the built-in screen reader is Narrator, which you can get to with `Settings > Ease of Access > Narrator`. However, NVDA and Jaws are more popular. After this paragraph is a screenshot of where to turn on Narrator. You can get NVDA at https://www.nvaccess.org/download/ and Jaws at https://www.freedomscientific.com/products/software/home-licenses/.

![The accessibility page on Windows 10 for turning Narrator on and off](https://dev-to-uploads.s3.amazonaws.com/i/jh26tsqnpt7bm8u7ctmu.png)

Now that you've got a screen reader, open the webpage in your browser and navigate to the poll options.

Navigating through the HTML elements is done with `Ctrl+Option+Right Arrow` on a Mac's VoiceOver, `Caps Lock+Right Arrow` on Windows Narrator, or `Down Arrow` on NVDA.

On VoiceOver, what I hear hopping through each element is:

1. The header to pick your favorite programming language
2. The names of each programming language
3. and finally, the word vote, with an indication that you're on a button

Our programming language divs are clickable (with `Control+Option+Space` on VoiceOver, `Caps Lock+Enter` on Narrator, or just `Space` on NVDA). However, notice that except on NVDA, the only HTML element where the screen reader actually tells us we can give input is the vote button.

Why don't all our screen readers know that, even though we gave our divs `onclick` handlers?

For that information, we need to look at the **accessibility tree**.

## Reading the accessibility tree

In addition to a DOM (document object model) tree for representing HTML and converting it to the user experience you get in a browser, there's another, related tree: the [accessibility tree](https://developer.mozilla.org/en-US/docs/Glossary/Accessibility_tree).

It's built from the DOM, and just like how the DOM tree creates the browser's visual user experience, the accessibility tree is read by accessibility technologies to make the user experience someone gets with tools like screen readers.

To start looking at the accessibility tree for a DOM element, right-click it and go to **inspect element**. Then in Chrome Developer Tools, click the **Accessibility** sub-tab of the **Elements** tab, and you'll see where your element is on the accessibility tree.

![Google Chrome's Developer tools, with the accessibility tab circled](https://dev-to-uploads.s3.amazonaws.com/i/0k0d6g7zjcay4wqal7ei.png)

Each object in the accessibility tree has a **name**, **role**, and optionally a **state** and **description**. So let's say you're looking at the accessibility tree object for Go. Its tree will look like this:

```
generic
  generic
    generic
      text "Go"
```

Each word `generic` represents an accessibility tree object whose role is "generic". Because a `div` HTML element is designed to play an arbitrary role in HTML, nothing about the div inherently tells the accessibility tree that our div is a piece of clickable input.

In fact, if you look at the third `generic` item, which corresponds to the actual button, you also won't find a `state`, even though in practice the state of one of our buttons is either selected or not selected.

Since we have a list of programming languages and we're only selecting one of them, the role we want our selections on the accessibility tree to have is `radio`. If the accessibility tree has an item with that role instead of the generic role, then screen readers will know to treat it as radio button input where you can only select one item in a group. There's three ways we can accomplish this:

* Use standard radio buttons.
* Give our divs the `radio` ARIA role, and write the JavaScript to [support the functionality](https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20160317/examples/radio/radio.html) a user would expect from a regular radio button when navigating with a keyboard.
* Get accessible HTML components from a framework or code library that does the JavaScript that the second bullet point mentioned.

While the first one isn't as flashy, it keeps the code simple to start with, so let's take a look at that.

> NOTE: If you want to see an example of the JavaScript for implementing the radio button role for divs, the World Wide Web Consortium has an example [here](https://w3c.github.io/aria-practices/examples/radio/radio.html). By the way, they also write the [Web Content Accessibility Guidelines](https://www.w3.org/WAI/standards-guidelines/wcag/), which are the standard for accessible web apps.

## Switching to radio buttons

While they might not look so exciting out of the box, an advantage of using built-in HTML elements is that a lot of them are designed so the accessibility tree, and in turn screen readers, automatically knows what to do with the elements.

This is called **semantic HTML**, and you can also find it on other HTML elements such as headers, and nav bars, and h1-6 tags.

To see this, let's see what our screen reader experience is like if we use radio buttons instead of divs.

```html
<form id="accessible-poll">
  <fieldset>
    <legend>Pick your favorite programming language</legend>
    <div class="language-radio">
      <input id="go" type="radio" name="language" value="go" />
      <label for="go" class="language-label">Go</label>
    </div>
    <div class="language-radio">
      <input id="javascript" type="radio" name="language" value="javascript" />
      <label for="javascript" class="language-label">JavaScript</label>
    </div>
    <div class="language-radio">
      <input id="ruby" type="radio" name="language" value="ruby" />
      <label for="ruby" class="language-label">Ruby</label>
    </div>
  </fieldset>
  <button>Vote</button>
</form>
```

We wrap our radio buttons in a `fieldset` so that they're grouped together, and give it a `legend` so the group of inputs is described on the screen reader. I also use a `label` for each radio button to associate the text with the radio button, as well as to make clicking the text count as selecting the radio button.

Hopping through the items on VoiceOver, I get:

1. The note to pick your favorite programming language and the indication that you're in an input group
2. The names of programming languages, and the indication that each item is one of three radio buttons
3. The indication you're at the end of the input group
4. and finally, the word vote, and the indication you're on a button

Not only that, but if I select a language, like Go, and then visit that radio button again on VoiceOver, the screen reader tells me that it's selected.

Before we look at the accessibility tree to see why a screen reader is now able to tell the user they're in a radio button group, there's just one other thing to do. I **don't** want it to be a takeaway of this tutorial that you need to sacrifice a visually appealing user experience to make your app accessible for screen readers. So let's add some CSS to make the radio button user experience look similar to the div user experience.

```css
fieldset {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  column-gap: 20px;
  margin-bottom: 20px;
  border-width: 0;
}

legend {
  font-family: sans-serif;
  font-size:   18px;
}

.language-radio {
  padding: 20px;
}

#go:checked + label {
  background-color: cyan;
}

#javascript:checked + label {
  background-color: rgb(250, 244, 72);
}

#ruby:checked + label {
  background-color: rgb(255, 21, 21);
}

.language-label {
  font-family:   sans-serif;
  font-size:     20px;
  text-align:    center;
  font-weight:   bolder;
  border-radius: 20px;
  border-color:  black;
  border-style:  solid;
  padding:       20px;
}
```

Sweet, now let's check out the accessibility tree!

## The accessibility tree for our radio input

Right click on the fieldset and click inspect element, and you'll see an accessibility tree that looks like this:

```
form
  group
    Legend
    generic
    generic
    generic
```

There's three generics, one for each div wrapping the radio buttons.

But click on one of the generics in the accessibility tree, say, the one corresponding to the Go button, and you'll see an accessibility tree that looks like this:

```
form
  group
    generic
      radio "Go"
```

As you can see:

* The outermost div's role is now "form", from the built-in `<form>` HTML element
* The built-in `<fieldset>` HTML element made the outermost div's role into `group`, indicating we're on a group of related inputs
* The div surrounding each radio button still has the role generic since it's a div and we didn't give it any ARIA attributes
* The radio button under the div, though, has the role `radio`, so the screen reader knows you're on a radio button

Not only that, but in the section titled **Computed properties**, you can see that:

* The radio button's name is "Go"
* Its role is "radio"
* It's `focusable`, so you can reach it by pressing tab
* It's not yet checked
* And it's labeled by the `<label>` tag next to it

Select the Go radio button, look at it in the accessibility tree again, and now its `state` is checked!

As you can see, the accessibility tree is useful for taking a closer look at what accessibility technologies like screen readers work with to build a keyboard and audio user experience. So when you're testing how a blind or visually impaired user would use your web app, the technologies your computer and browser already had pre-installed can go a long way!

> Shoutout to Tim Ringenbach for peer-reviewing my post, and to my mom for letting me borrow her Windows computer for trying out Windows screen readers!