Accessible modal dialogs: A tricky minefield

We at BarrierBreak get to look at a lot of sites and analyse their accessibility errors and successes. One of the most common pain points we find are inaccessible modal dialogs.

Modal dialogs have always been common, but it seems in the last few years, their popularity has increased. From sign-up forms, to dialogs asking you to subscribe to your newsletters, or even simply error notifications, many of these patterns are implemented using modal dialogs.

A large portion of these modal dialogs are inaccessible, which means a major component of the web is out of reach to people (these can be keyboard-only users, or screenreader users, or a combination of both). Fortunately, there are ways to make modal dialogs accessible. We just need to keep in mind a few basic principles.

It’s all about focus

If your modal dialog can be 100% operated using a keyboard, then chances are you are on the right track. A common error with many implementations of modal dialogs is that they don’t keep in mind keyboard focus and assume everyone has a mouse to click on elements.

As a user, I should be able to:

  • Have the initial focus inside the modal dialog as soon as the dialog is opened. It shouldn’t be anywhere on the main page.
  • Close the modal using my keyboard.
  • Tab through various focusable elements (like form input, buttons etc) using just my keyboard.
  • Stay within the modal. Keyboard focus should not leak to anywhere in the background (the main page) as long as the modal window is present. Keyboard focus should be trapped inside the modal window as long as its present.

Ideally, when the dialog is closed, the focus should go back to the element that spawned the dialog.

Dimming the background

In the cases of modal dialogs, its a good idea to dim the background with something like a translucent grey color just to emphasise the fact that the background is not in focus. When the background is greyed out, and the modal window is not, it gives an extra indication that the user is supposed to pay attention to the modal dialog.

This won’t matter much to screenreader users, but to sighted users, its a helpful practice.

ARIA and Hiding things properly

Just because an element isn’t visible doesn’t mean its hidden. If not implemented properly, it can still be seen using a screen reader.

It’s important to use aria-hidden=“true” in cases where we want to hide an element from the screen reader.

  1. When no modal dialog: The main page has aria-hidden=“false”. Modal dialog has aria-hidden=“true”.
  2. When modal dialog is in play: The main page has aria-hidden=“true”. Modal dialog is aria-hidden=“false”.
  3. When modal is closed: Go back to step 1.

We should also add additional semantics to divs and buttons to let the screenreader know what an element is supposed to be doing. For example dialog has the correct aria role attribute (role=“dialog”). If you have a close button, have a aria-label attached to it which describes it’s intent. For example, <button aria-label=“exit dialog”>X</button>. This is especially true if you’re using an non-text component (which also doesn’t have an alt attribute) in your button which is essential to understanding functionality. A common example of this are icon fonts.

Also, try using aria-labelledby to describe the title of the dialog, and aria-describedby to assign a description of the dialog.

HTML5 and Polyfills

The modal dialog is such a common pattern that we have an element in HTML5 for it called the <dialog> element. What makes this element great is that it takes a lot of the HTML and JS things we code for, and has it baked into the element itself. For example, it has DOM APIs to show and hide the modal, so we don’t have it code them ourselves. It has a ::backdrop CSS pseudo class to style the backdrop a certain way.

Keep in mind that not all browsers have support for the dialog element yet. So using a polyfill such as the this one from the Google Chrome team is essential.

Existing solutions and further reading

If you’re looking for a library for existing implementation to learn from, then do take a look at a11y-dialog which is fork of the Incredible Accessible Modal Window. I prefer the former over the latter because its not dependant on jQuery and has a JS API, a DOM API and event handling.

If you’re a fan of Web Components, then take a look at <paper-dialog> from the Polymer team.

That’s all you need to know for making great accessible modal windows.