Recently I was required to implement accessible modals for a client's new pattern library. I was open to using an existing module, but wanted to avoid anything with additional external library dependencies, as the amount of overall interaction across the site was low.

I came across some great solutions like a11y-dialog and a11y-modal. But I already had some code that covered the class-toggling functionality, so I decided to not to duplicate it, and instead extract the key accessibility-related components of the existing modules.

What I discovered is that in addition to standard dialog ARIA-roles, focus management is crucial if you wish to build a more accessible modal dialog. The key criteria are set out in WAI guidelines, and Nicholas C. Zakas's has an excellent description of what is involved.

The key functionality, from Using ARIA role=dialog to implement a modal dialog box:

Scripted focus management should therefore

  1. move the keyboard focus from the triggering element (link or button) to the custom dialog (or one of the focussable elements within it)
  2. keep it within the custom dialog until the dialog is closed (this makes the dialog effectively modal)
  3. move it back to the triggering element when the user closes the dialog by activating one of the choices offered.

Additionally important is ensuring the esc key performs the expected action.

The final solution involved a small module that is only involved in focus management that sets, traps, and removes focus of specified elements. You can see it in action in this Codepen. It's only a small amount of additional code, but the end result is a modal dialog that is not only much more accessible, but more robust for all users.