In the previous article, we unveiled the magic behind semantic code and using native elements in designing usable sites. Remembering to keep a mindset of accessibility and inclusivity, we journey onward in the third and final article in this series. Destination: screen readers. You’ll come away with everything you need to know to get your hands dirty when it comes to designing, developing for, and testing your sites with screen readers.

Article Series:

Now that we have learned about the importance of thinking in accessibility, and using native elements when it comes to designing sites that are usable, let’s turn our attention towards learning about screen readers.

As I began to work with screen readers, it was sheer curiosity that propelled me to dive in fearlessly. I knew it was something I wanted to learn, so I rolled up my sleeves and got to work. In this post, I will share with you the basics of screen readers: how they are used and commands to know. I’ve included a demo to show a few common problems with solutions as you’re getting started.

Keep in mind, any journey involving learning is ongoing. Let your accessible and inclusive mindset form a solid foundation upon which you can add new knowledge.

How people use screen readers

I took a Communications class in high school, and during each class we were encouraged to read the newspaper as a way of staying up to date on current events. We were taught a handy technique while reading the paper, which was to quickly scan each headline of the top stories. If something stuck out as interesting, we could make a mental note and return to read the story after scanning the rest of the newspaper headings.

In the same manner, people who use screen readers are able to scan through and read the headings of a web page (I’ll show you how you can do this too, later in the article.) This is a great way to quickly gain an understanding of the content available on the page and whether it’s something of interest and worth returning to.

For this very reason, it’s vital to make sure heading elements are present and structured in a logical order. Start with one h1 which would describe the overall purpose for the page, the main “headline.” This would be followed by subsections of content using h2 elements, and perhaps a subsection of that section, using an h3, and so on. Tip! Don’t use a heading element purely for the stylistic effect. If you need a heading to look a specific way, add a class attribute and use CSS to make it look how you need. Also, keep in mind that the visual appearance of headings is important, since it helps people who have difficulty reading or who have other cognitive issues gain an understanding of the page structure as well.

People using screen readers can also quickly scan the page for content by using links. Screen readers often feature a way to navigate site content by announcing each link on the page, in a list format. People can decide on whether they’d like to follow the link or not, based on the link text. For this reason, it is crucial that link text is both unique and descriptive. It can become a frustrating user experience when all the links on a page are announced as “Read More” and no extra context is given as to where the link leads.

You can also simply use the Tab key to move around and discover interactive content. This is a common method of navigation and gaining an understanding of the page, but it’s not quite as fast as navigating by element type and only accesses elements that are focusable.

And what about non-focusable elements, you may ask? Don’t fret, I’ll show you how to access things like plain text and images in the next section!

Let’s look at a few screen reader commands in more depth.

Screen reader commands devs should know

If you’re on an Apple desktop or laptop (or even mobile device), you’ve got a screen reader called VoiceOver right at your fingertips. If you’re using Windows, there’s a free, open source  screen reader called NVDA available to install. Tip! Pair up VoiceOver with Safari and NVDA with Firefox. These are the most commonly used browsers with these screen readers.

To start VoiceOver (VO), press the Cmd + F5 keys. VO will start reading the page or application you’re currently looking at. You can Cmd + F5 again to quit out of VO.

Start NVDA by pressing Ctrl + Alt + N. Alternatively you can use the Windows Run dialog and enter, “nvda”. One method to quit out of NVDA is to use the Run dialog again and enter “nvda -q”.

Use your computer’s volume control to adjust the voice volume as needed.

Modifier keys

Modifier keys are screen reader specific shortcut keys. They are used with other keys on the keyboard to execute various instructions to the screen reader.

The modifier key for VO is Ctrl + Opt. For NVDA, by default, the modifier key is Insert. This can be changed in the configuration to be Caps lock if you’re on a laptop.

For example, to start reading a web page using NVDA, you could press Insert + Down arrow and NVDA will begin to read from the current position.

Tabbing around

When you have either VO or NVDA enabled, use the Tab key to move in a forward direction through interactive elements on the page or Shift + Tab to move backward. Depending on your browser settings, by default, elements on the page that you can tab to would be things like links, buttons, or form controls. Moving around in this fashion is considered using the “browser cursor.” The browser cursor moves focus around from one focusable element to the next. While this is quite handy for keyboard-only users, there is another cursor which can move to non-focusable items and describes the content on the page with greater detail, the “screen reader cursor.”

Screen reader cursor

VO and NVDA have their own built-in cursors which people can use to move around the page and read other content, not just focusable items.

To use the VO cursor, hold down Ctrl + Opt, then use the Left or Right arrow keys to move around and have VO announce all types of content on the page. NVDA’s cursor is moved about by using the Up and Down arrow keys. This reads one line of content at a time.

Reading the page in this manner reveals more page content, including plain text, image alt-text, and page headings. This is a great way to test and hear how text content sounds, and if descriptive image alternative text makes sense with what’s being displayed in the image.

Advanced navigation

Both VO and NVDA offer a way to navigate page content by grouping like elements together. Each screen reader is able to display a list or menu of like items, separated by categories, in order to quickly move around the current page and easily discover what content is available.

VO Rotor

The VO Rotor is essentially a menu of different types of elements on the page, broken down into categories. To open the Rotor, hold down Ctrl + Opt then press the U key. A new VO window will appear overtop of the page with a list of items.

When the Rotor is open and available for navigation, use the Left and Right arrow keys to move between element categories such as headings, links, landmarks, or form controls. Use the Up and Down arrow keys to navigate through the listed items. Use the Esc key to exit out from the Rotor.

NVDA Element List

NVDA also has a menu of elements on the page called the Element List. To open the list, use the Insert + f7 keys.

When the Elements List is open, use the Left and Right arrow keys to move through the types of elements. Press the Tab key to move down into the list. Once in the list, use the Up and Down keys to move through the list items.

There are many more shortcuts and keystrokes available for these screen readers, but these are just a few easy ones to learn to help you get started.

Next we’ll take a look at a demo site and use VoiceOver to navigate through the page elements, searching for potential accessibility issues.

Demo!

Let’s look at a before and after example of a demo site. It’s important to remember: when investigating issues, always check first to see if you’ve used the right elements as they were meant to be used. Often, there’s no need to create a complex solution to fix a problem when a more semantically structured solution will do the trick.

In the two demo sites linked below, you will notice that the example pages look the same, but the code underneath is quite different. If you were to use your mouse to navigate around and submit the form, they work perfectly well just the same. However, what happens when someone using a screen reader or the keyboard alone navigates the page and tries to fill out the form?

Listen to the following video as I use VoiceOver to navigate through the page elements. What do you notice?

(Try it yourself! Open Demo 1 on Codepen)

It looks like the screen reader got hung up on a few things:

  • When the logo link image received focus, it didn’t sound like descriptive information. What was it supposed to represent?
  • Did you notice the navigation links were skipped entirely? What happened there?
  • Each form input was announced as such, but what were they for? What type of data was expected?
  • The form submit button seemed to have been skipped as well? How could someone submit this form using just a keyboard?

Let’s address these issues and see what went wrong.

Target Element Problem Solution
Logo Link When the logo link received focus, the embedded image alt attribute text was announced. In this case, since there was no alt attribute present, the image file name was announced. This can easily be remedied by adding an appropriate image alt text value. In this instance, it should match the text of the image itself.
Navigation Links When we inspect the markup for the navigation links, we see there is a custom JavaScript onclick event and no href attribute. Links without the href attribute will not receive keyboard focus which is why they were skipped. We can fix this quite easily by adding an href attribute for each link, adding the appropriate page URL as the value, and removing the custom JavaScript onclick event as this is no longer required.
Form Inputs The form input elements gave no context for their intended purpose or expected data. This is a result of the inputs not having an associated label to help explain the purpose of the control. We need to add a label element and set its for attribute to match the value of the id attribute of the input. Now when the element receives focus, its label will be announced alongside the element role.
Submit Button The submit button was skipped because, well, it’s not a button at all. The element is actually a span with a custom JavaScript onclick event and CSS styles to make it appear as a button. We can easily make this element keyboard accessible by changing the span into a button element. With this change, the button will be focusable and announce its role as “button,” which indicates that the Space key can be used to submit the form.

After fixing these issues, let’s listen to the page again and see what things sounds like.

(Try it yourself! Open Demo 2 on Codepen)

After listening through the page again, we gain a much clearer idea of the content. The main logo image has an alt attribute which announces the text embedded within the image. Each of the main navigation links are able to receive focus and are announced as a link element. Each form input is announced along with its label, revealing what type of content is expected. The form submit button is announced as such, receiving focus and fully supporting the keyboard interactions available to a button element (Space or Enter key presses.)

There were also a few additional adjustments made to add even more semantic meaning to the elements on the page:

  • The header, nav, and main HTML elements were added as wrappers for their respective content. These create “landmarks” within the page. Someone using a screen reader could now have the option to navigate by landmarks, as well as headings and links, etc, when using the VO Rotor or other shortcut keys.
  • A ul list element was used to give extra context and structure to the navigation area. This helps to give notice on how many links are present when entering the list, as opposed to someone having to tab through each link to gain this understanding.
  • The main title of the page is now wrapped with an h1 element, allowing for heading navigation and to give notice to the overall purpose of the page. Another optional attribute added to this element was tabindex. Giving this attribute a value of 0 adds the element to the natural browser tab order, which means this element will receive focus and be announced by the screen reader.

Testing with a screen reader (and tabbing through your pages using only a keyboard) by following the browser or screen reader cursors and attempting to complete tasks with just a keyboard will tell you a lot about how accessible your code is and whether it will make sense for people using assistive technology. If something doesn’t sound quite right or is unreachable, there are issues that need to be addressed before shipping to a production environment. As mentioned earlier, screen reader compatibility isn’t synonymous with full accessibility (there are a lot of other considerations for other types of users), but creating semantically structured code that’s fully accessible to a keyboard goes a long way in helping both sighted and non-sighted keyboard users.

Start with accessibility in mind. Test with various screen reader + browser combinations. Test early and test often. Be sure not to add accessibility on as a feature after launch as this rarely works out in the end, and people will notice.

With great power…

I’ve given you enough to get started with how screen readers are used and how you can test your pages with screen readers, but I’d be remiss if I didn’t leave you with possibly the most important thing to know about accessibility development: screen readers are just the beginning.

Even on our own team, screen readers are where some of us started our accessibility journey. Developers are fascinated by the technology and it’s the first thing we get into. Still, learning to use and test with them really is just a start. It’s the first point on a much longer journey that includes considering the wide range of people’s abilities, situations, and all kinds of use cases.

I hope this series on “Listening to the Web” has inspired you to make positive changes in your daily workflow. I urge you, fellow web developer, to take the plunge and dive deeper into web accessibility. Learn all you can, and share what you’re learning. Get feedback and support from the greater web community. Put in the extra effort, even when not budgeted for. Eventually, it won’t be extra effort at all but simply part of your daily workflow. One person can make a difference.

Start with accessibility in mind, listen to the web, and make awesome things for everyone.