But enough with the introductory talk! Have fun!

Great focus management is essential

It’s important to make sure that our websites are navigable by keyboard. A lot of users rely on a keyboard when they surf the web. Among them are people with motor disabilities, blind people and people who don’t have hands or cannot use a mouse or track pad for whatever reason.

Navigating a site via keyboard means jumping from one focusable element to another in DOM order. This is usually accomplished by using the Tab key or Shift + Tab for the reverse direction. Focusable elements are amongst others links, buttons and form elements. They can be selected with the Enter key and sometimes the Spacebar . By being focusable and selectable in different ways they come with very useful default functionalities. Therefore it just makes sense to use correct semantic elements and write HTML in a logical order.

Elements like <p> , <h2> or <div> cannot be focused by default. We often use tags like these to create custom components powered by JavaScript, which might be problematic for keyboard users.

Making non-focusable elements focusable

It’s possible to make non-focusable elements focusable by adding the tabindex attribute with an integer value. If the value is set to 0 the element becomes focusable and reachable via keyboard.

If the value is a negative number, the element is focusable (e.g. with JavaScript) as well, but not reachable via keyboard. You can also use a value greater than 0 , but that changes the natural tab order and is considered an anti-pattern.

<h2 tabindex="0">A focusable heading</h2>

If you want to learn more about tabindex , watch the A11ycasts episode Controlling focus with tabindex by Rob Dodson.

Focusing elements with JavaScript

Even if elements are focusable, sometimes they are not in the right DOM order. To illustrate that I created a simple modal window component in HTML, CSS and JS (Demo and editable Pen).

If you use the Tab -key to jump to the button and press enter, a modal window will pop up. If you press the Tab -key again, the focus will jump to the next link visually below the modal window. The expected behavior would be that the next focused element is within the modal window. But it's not because elements are focused in DOM order and the modal window is located at the bottom of the document. You can see that in action in the following screen recording.

A short video which illustrates bad focus management.

To fix that you have to make the modal window focusable and then focus it with JavaScript.

HTML

// Add tabindex="0"

<div class="modal" id="modal2" tabindex="0">

...

</div>

Javascript

// Use the focus() method to set focus

function showModal() {

... var modal = document.getElementById('modal2');

modal.focus(); ...

}

You can see that in action in the updated example (Demo and editable Pen) by tabbing to the button, pressing enter and tabbing again. You’ll see that the modal window itself is focused now.

This is great, but there are still two issues here.

If you close the modal window by pressing Esc the focus is lost. Ideally, the focus would jump back to the button where it was before you opened the modal window. In order to achieve that you have to store the last focused element in a variable.

document.activeElement gives you the current element in focus.

// Variable for storing the last focused element

var lastFocusedElement; function showModal() {

... // Store the last focused element

lastFocusedElement = document.activeElement; var modal = document.getElementById(modalID);

modal.focus(); ...

}

Now that you have a reference to the button you can focus it again when the modal window is closed.

function removeModal() {

... // Return the focus to the last focused element

lastFocusedElement.focus(); ...

}

I’ve updated the code in another Pen (Demo and editable Pen). The accessibility is way better now, but there’s still room for improvement.

It’s advised to the keep the focus within the modal window when it’s opened. Right now it’s still possible to tab out of the modal.

I won’t go into detail here, but for the sake of completeness I made a fourth Pen with a so called keyboard trap (Demo and editable Pen). The focus will stay within the modal window as long as it is active.

A short video which illustrates good focus management.

If you compare the first and the last Pen you will see there isn’t a lot of extra code. It’s probably not perfect, but the final solution is much nicer to use.

There is another example for an accessible modal and a great article called Using tabindex by people from Google.

If you want to learn more about keyboard testing visit the WebAIM website. They provide a list „of the most common online interactions, the standard keystrokes for the interaction, and additional information on things to consider during testing.“ For more examples of focus management, check out the egghead.io video „Focus management using CSS, HTML, and JavaScript“ by Marcy Sutton or the A11ycasts episode „What is Focus?“ by Rob Dodson.

If you need a button, use the <button> element

I already wrote about buttons in the first article, but apparently a lot of people use generic elements as buttons. So, I guess it does no harm to write some more about that topic.

I made a Pen (debug mode / Pen with code) to illustrate some of the issues of using a span or div as a button over a button or input element. If you tab through the page you will experience that you can focus the first button, but not the second one. The reason for this is – of course – that the first button is a button and the second one a div . You can work around that issue by adding tabindex="0" to the div , which makes an initially non-focusable element focusable. That's why the third and fourth button are focusable even though they're div s.

// Button and focusable

<button class="btn">I'm a button</button> // Div and not focusable

<div class="btn">I'm a div</div> // Still just a div, but focusable

<div class="btn" tabindex="0">I'm a div</div> // Button role and focusable

<div class="btn" tabindex="0" role="button">I'm a div</div>

The div-button is indeed focusable but still behaves like a div , even if you add a role of button . To illustrate that, I added a simple click event handler to all .btn elements (Pen). If you click the buttons an alert box will pop up, but if you try do the same using keys ( Enter or Spacebar ), only the first button will trigger an event. You would have to add a key event handler to the div-buttons to fully mimic the default button behavior, which seems like a lot of unnecessary overhead, doesn't it? That's why you should use the <button> element if you need a button.

Watch the A11ycasts episode „Just use button“ by Rob Dodson or read Links, Buttons, Submits, and Divs, Oh Hell by Adrian Roselli for more details and examples.

Screen reader users must be informed when content changes dynamically

Usually, screen readers only announce content when an element is focused or the user uses his/her screen reader’s own navigation commands. If content is loaded dynamically and inserted into the DOM, only sighted users will be aware of the changes. ARIA Live Regions provide several options to work around that issue. I’ll show you how in an example.

Let’s say you have a profile settings page where you’re able to edit personal data and save it. When the save button is clicked changes are saved without reloading the page. An alert informs the user whether the changes where successful or not. This may happen immediately or take some time. I recorded a quick video to show you what I just explained.

A video illustrating ARIA Live regions

You can see that the action was successful, but you can’t hear it. Screen reader users won’t notice the change, but there’s a simple solution for this issue. By adding a role of status or alert to the message box screen readers will listen for content updates in that element.

<div class="message" role="status">Changes saved!</div>

If the text of the message changes the new text will be read out. You can see and hear that in action in this video and take a look at the code in this Pen.

Be polite to your users

The difference between status and alert is that an alert will interrupt the screen reader if it's in the course of announcing something else. status will wait until the screen reader has finished announcing.

There’s another attribute called aria-live, which can take three possible values off , polite or assertive . off is the default value, aria-live="polite" is equivalent to role="status" and aria-live="assertive" to role="alert" . In some “well-known predefined cases it is better to use a specific provided “live region role””. Also if a browser doesn't support role you may want to try using both attributes. Léonie Watson shared some test results in „Screen reader support for ARIA live regions“.

<div role="alert" aria-live="assertive"></div>

Sometimes it makes sense to announce more than just the content that has changed

By default screen readers only present content that has changed, even if there is other content within the same live region, but it occasionally makes sense to announce the whole text.

It’s possible to change the default behaviour with the aria-atomic attribute. If you set it to true , assistive technologies will present the entire contents of the element.

There is an aria-atomic test case demo by Paul J. Adam that compares different live region settings. He also tested his demo with VoiceOver on iOS 8.1 and recorded it so you can see it in action. I suggest you watch the recording (VoiceOver iOS 8.1 Speaking Characters Remaining aria-atomic & aria-relevant on aria-live regions) if you want to better understand possible use cases for aria-atomic .

Some things to consider

Live Regions do not move focus, they just trigger announcement of text

Use alert only for critical changes. status is better in most cases, because it's politer.

only for critical changes. is better in most cases, because it's politer. Avoid designing alerts that disappear automatically because they may disappear too quickly

During my tests, I had issues with VoiceOver. Hiding the alert using CSS or creating it dynamically didn’t work all the time. Make sure you test your Live Regions thoroughly in different browsers with different software.

Of course, there’s an A11ycasts episode „Alerts!“ by Rob Dodson for more details and examples. Heydon Pickering has another example for live regions in his collection of ARIA examples.

You don’t have to guess which usage patterns your widgets must provide

It’s often hard to think of all the features a widget must provide in terms of navigation and accessibility. Gladly there’s a resource called WAI-ARIA Authoring Practices 1.1 that helps us with that. „WAI-ARIA Authoring Practices is a guide to understanding how to use WAI-ARIA to create an accessible Rich Internet Application. It describes recommended WAI-ARIA usage patterns and provides an introduction to the concepts behind them.“

They have guides for building accordions, sliders, tabs, and more.

Accessible JavaScript components

There are also great resources with accessible JavaScript components.

If you know additional resources please share them in the comments.

Recap

Leverage the advantages of JavaScript to improve your site’s accessibility. Take care of focus management, inform yourself about common usage patterns and consider screen reader users when you manipulate the DOM. Above all don’t forget who you are making websites for and have fun while you’re at it.

Going beyond

That’s it for now. I hope that these tips will help you write more accessible HTML. A big thanks to Heydon Pickering, because his book „Inclusive Front-End Design Patterns” built the foundation of most of the stuff that you’ve just read. If you want to learn more about accessibility and inclusive design I highly suggest you read his book.

More accessibility tips

This article is the second one in a series of four. The others are in the works and soon to be released.

Writing HTML with accessibility in mind Writing JavaScript with accessibility in mind Writing CSS with accessibility in mind Up next: Learn how to design and develop with accessibility in mind

Thank you for reading and please don’t forget to like and share this article if you enjoyed it.

Special thanks to Adrian Roselli for helping me with this article and Eva for proofreading my writing.

While I work on the next post, you can check out some other stuff I wrote:

Resources