Trapping focus is one of the important issues concerningaccessibility. In case of assistive technology (like screen readers)users, or keyboard users,trapping focus is a must.
We are going to talk about How to Trap Focus inside of a modal as long as it is open and transfer focus to the rest of page once it is closed.
Let’s see what we have here.
Hint: If you only want the code snippet, just go to “Trap Focus Method” section.
According to Ally.js library an HTML element can be a member of exactly one of the following five categories:
Inert: The element is not interactive and thus not focusable. And should not be focused by script (except in rare cases).
Focusable: The element can be focused by script Element.focus() and possibly the mouse (or pointer), but not the keyboard.
Tabbable: The element is keyboard focusable (“tabbable”), as it is part of the document’s sequential focus navigation order. The element is also focusable by script and possibly the mouse (or pointer). It is important to note that this navigation order is the same as DOM order.
Only Tabbable: The element is only keyboard focusable, possibly by the mouse (or pointer), but it cannot be focused by script.
Forward Focus: The element will forward focus to another element instead of receiving focus itself.
Here is a table of Browser Compatibility of Focusable and Tabbable Elements. It shows which elements are tabbable, focusable, or inert and its compatibility with different browsers.
The attribute tabindex is a global HTML attribute. It decides which element could be focused and puts it in the sequential focus navigation order (or simply tab order).
Its value can be one of three:
tabindex="-1" removes the element from tab order but it can be focusable by script.
tabindex="0" put the element in the tab order and its order is affected by to DOM structure. Note that the visual (CSS) structure does not affect tab order. Therefore, it is a good practice to have a similar viasual and DOM order not to confuse keyboard users.
tabindex="1" meaning that the element should be focusable in sequential keyboard navigation, with its order defined by the value of the number in an ascending manner. So
tabindex="2" will precede
tabindex="3". This is Anti-Pattern and should be avoided because you will end up jumping between elements and this would cause confusion.
It sets focus on a specified element. This does not mean that it outs the element in the tab order, but it drags focus to it in a certain event using script. It can be used to a focusale or not unfocusable element.
The optional focus option is a boolean value.
false method will scroll the element into the visible area of the browser window.
true (default) method will not scroll the element into the visible area of the browser window.
This a simple page example contains:
Sign in button. It is not a button in fact. It is just a div acts like a button. That’s why I added
tabindex="0" attribute to it.
Form consists of a Text box and a button.
Modal that pops up when you click Sign in button or press enter while it is focused. It contains:
The required behavior is that when the modal is open focus is trapped inside it and does not reach other elements until modal is closed.
What did I do?
When the Sign in button is clicked or pressed “Enter” upon, I opened modal, remove elements outside modal from tab order, and start focusing on the first focusable element of modal.
Inside modal I took care of the first and last focusable elements, to ensure that when user reaches the last element for example the first element will be the target of the next tab, and when user presses “shift+tab” while on first element, it will bring focus to the last element. So Focus is trapped inside the modal as long as it is open.
When user click or press “Enter” while on Log on button, the modal disappears, and all other elements return focusable again.