Into the nitty-gritty of accessibility
TLDR; Implement trap focus with modals and dialogs even when using the new dialog element.
The <dialog>
element, which landed in major browsers in March 2022, is a very welcome addition to the HTML language which until then lacked a native way to create dialog boxes. It has interesting features, like special methods to open and close, the ::backdrop
pseudo element, built-in support for closing with the Esc
key and more.
We recently updated Ripple's Modal component to use <dialog>
under the hood and noticed it handled focus trapping in a slightly different way from what we were used to (and the way we had implemented it in our component). Trapping focus is a way to ensure keyboard focus remains on relevant elements. A modal is a design pattern asking users to take an action before they can return to the page. The rest of the page becomes temporarily unavailable. For mouse users, this is conveyed visually by the modal sitting on top of the rest of the content; Ripple's Modal also applies an overlay to the rest of the page behind the modal, darkening it and effectively disabling any interactive element. To achieve the same user experience for keyboard users, it is important that only elements within the modal are focusable while it is open.
As expected, <dialog>
automatically removes the rest of the page from the tabbing order, but the focus sequence is not limited to the elements within the modal. Instead, after the last element (or before the first one, when tabbing backwards with Shift + Tab
), focus goes to the browser chrome (the address bar specifically).
The behavior varies depending on the browser. In the latest version of Chrome as of this writing (122.0.6261.129) a single tab stop is added (for the address bar). In Firefox (124.0.1), several stops are added as many of the browser's interactive elements are tabbable.
The Ripple team first considered this to be a desirable change, comforted by accessibility expert Scott O'Hara's take:
While a modal <dialog>
is open, keyboard focus cannot return to the document beneath it. However, unlike many custom modal dialogs which typically create a focus trap – forcing an endless loop of the focusable elements within the dialog – a native modal <dialog>
allows keyboard focus to escape the modal and return to the browser’s chrome (e.g., the address bar and other such controls). This is good behavior, not a bug. Completely trapping keyboard focus within a custom dialog, thus not allowing focus to return to the browser chrome, was always more of a “it’s either this, or focus can move back to the document”. If this behavior seems confusing or undesired to you, that’s unfortunately due to the fact that you’ve had to experience custom dialog behavior for so long…
But Watermark's Director of Accessibility Program Srinivasu Chakravarthula begged to differ. For him this change was an accessibility issue. On his side is accessibility expert Nolan Lawlon and, according to him, most accessibility experts.
A very civil conversation ensued between Vasu and I:
In the end we agreed to keep the current user experience to minimize possible disruptions. Users will not be taken aback if nothing changes. We might revisit this solution in the future if the new user experience becomes familiar enough to users.
In the meantime, for consistency across Watermark products, please ensure focus is always trapped within the modal and doesn't escape to the browser chrome. Also remember that the user can jump to the chrome using other keyboard shortcuts (e.g. ctrl+L for the address bar), so you should always ensure your focus trap works not only when focus is already inside the modal but also when entering the page. The <dialog>
element will take care of this by default. If you're not using it, set an event listener on the <body>
element as long as the modal is open, to redirect focus inside the modal.
The questions raised by this technical point serve as a useful reminder that when it comes to accessibility, there isn't always a clear, unambiguous answer. When I first started working in the field of accessibility, I expected to have to check a series of requirements in order to ensure that a page or app was accessible. But accessibility is just like the rest of web design and development: in very few cases are we able to apply a textbook solution. In all others we adapt to the particular cases and work out an ad-hoc solution, which might be revisited later as technology evolves, or as we figure out better solutions.