How To Trap Focus Inside a Modal.
Tags: a11y, webdev, javascript, html
Published: 2019-02-06 11:05:00

---
title: How To Trap Focus Inside a Modal.
published: true
description: This article shows a practical way to trap focus inside a modal and optimize tabbing order using JavaScript.
tags: Accessibility, webdev, JavaScript, html
---
<img class="graf-image" data-image-id="0*Pw1mWlzR9TtF4VvF" data-width="3648" data-height="2432" data-unsplash-photo-id="5ydw9eqUGgU" src="https://cdn-images-1.medium.com/max/720/0*Pw1mWlzR9TtF4VvF" data-delayed-src="https://cdn-images-1.medium.com/max/720/0*Pw1mWlzR9TtF4VvF">

Trapping focus is one of the important issues concerning accessibility. 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._

**Contents:**

<ol>
    <li>Terminology.</li>
    <li>tabindex Attribute.</li>
    <li>Element.focus()</li>
    <li>Trap Focus method</li>
    <li>Resources.</li>
</ol>

___

####_**Terminology:**_

According to [Ally.js](https://allyjs.io/what-is-focusable.html) library an HTML element can be a member of exactly one of the following five categories:

1.**Inert:** The element is not interactive and thus not focusable. And should not be focused by script (except in rare cases).

2.**Focusable:** The element can be focused by script `Element.focus()` and possibly the mouse (or pointer), but not the keyboard.

3.**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.

4.**Only Tabbable:** The element is only keyboard focusable, possibly by the mouse (or pointer), but it cannot be focused by script.

5.**Forward Focus:** The element will forward focus to another element instead of receiving focus itself.

Here is a [table](https://allyjs.io/data-tables/focusable.html) of Browser Compatibility of Focusable and Tabbable Elements. It shows which elements are tabbable, focusable, or inert and its compatibility with different browsers.

___

####_**tabindex Attribute:**_

<img class="graf-image" data-image-id="0*L8MSwMvmKl_QKQ9G" data-width="4378" data-height="2980" data-unsplash-photo-id="WAVrMzcUI6I" src="https://cdn-images-1.medium.com/max/720/0*L8MSwMvmKl_QKQ9G" data-delayed-src="https://cdn-images-1.medium.com/max/720/0*L8MSwMvmKl_QKQ9G">


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:

1.**Negative value:**  `tabindex="-1"` removes the element from tab order but it can be focusable by script.

2.**Zero value:**  `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.

3.**Positive value:**  `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.

___

####_**Element.focus():**_

<img class="graf-image" data-image-id="0*560i5u5CYDL89-7u" data-width="2256" data-height="1496" data-unsplash-photo-id="NaaiDPPlXwk" src="https://cdn-images-1.medium.com/max/720/0*560i5u5CYDL89-7u" data-delayed-src="https://cdn-images-1.medium.com/max/720/0*560i5u5CYDL89-7u">

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.

_Syntax:_

`Element.focus([option])`

The optional focus option is a **boolean** value.

If `false` method will scroll the element into the visible area of the browser window.

If `true` (default) method will not scroll the element into the visible area of the browser window.

___

####_**Trap Focus Method:**_

Here comes the exciting part. In this article we will tackle trapping focus inside a modal using JavaScript Of course, it is not the only method.

_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:

**_Two Text boxes_**. One for user name and the second for password entry. And finally a Log in button.

{% codepen https://codepen.io/islam8/pen/BPvazR default-tab=js,result %}

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?_

1. 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.

2. 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.

3. When user click or press “Enter” while on Log on button, the modal disappears, and all other elements return focusable again.

___

####_**Resources:**_

[How to get the first and last focusable element in the DOM.](https://gomakethings.com/how-to-get-the-first-and-last-focusable-elements-in-the-dom/)
[Focusable Elements — Browser compatibility table.](https://allyjs.io/data-tables/focusable.html)
[What does Focusable mean?](https://allyjs.io/what-is-focusable.html)
[HTMLElement.focus()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)
[Element.removeAttribute()](https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute)
[NodeList.](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
[Creating keyboard shortcuts using JavaScript.](https://medium.com/@melwinalm/crcreating-keyboard-shortcuts-in-javascripteating-keyboard-shortcuts-in-javascript-763ca19beb9e)
[Find Element based on Attribute Value.](https://stackoverflow.com/questions/2694640/find-an-element-in-dom-based-on-an-attribute-value#16775485)