JavaScript: How to create a looping tabindex cycle

Let’s say you have a modal with a form in it and you want to have tighter control over what happens when the user uses the Tab button on their keyboard. Without setting controls, it is possible for the user to tab through the text boxes in the modal and change the focus to other form elements below or behind the modal. Fortunately, HTML comes with a feature called “tabindex” that allows the developer to specify the tab order of an element. This can work on a series of links, divs, or form elements.

This works by setting number values to the key word “tabindex” on your page. For example: tabindex=1, tabindex=2, tabindex=3, etc..

In this article I will describe the steps that are needed to create a controlled tabindex cycle that loops back on itself either forward with the Tab key or backward with the Shift + Tab key.

Here is a working example, loaded in an iframe:

I in this example, I used an HTML “autofocus” to make the initial focus in the form on (showing up in light green) the text box with 8.5 in it. This is the text box that represents the first box in the tabindex cycle. The autofocus right before the closing bracket is what make the initial focus appear in this box:

<input type="text" id="finished_size_width" class="paper_update autofocus1" style="width: 40px;" placeholder="8.5" tabindex=2 autofocus>

The tabindex cycle can be seen by hitting the Tab key over and over. You can see the focus switch from one form element to the next (light green) until the focus goes from the bottom text field back up to the top again. This works in reverse also by clicking Shift + Tab.

Step 1: Add tabindex values to your HTML form elements

When a user uses the Tab button to “tab” between elements on this page, the tabbing will start at tabindex=1 and continue up to the last tabindex you have defined. This is the first step in creating a looping tabindex cycle.

Here is an example of what it looks like to add tabindex values to HTML form elements. These text boxes are in the tab order from tabindex=5 through tabindex=8:

<input type="text" id="margin_top" class="paper_update" style="width: 50px; margin-right:20px;" placeholder=".5" tabindex=5>
<input type="text" id="margin_right" class="paper_update" style="width: 50px; margin-right:20px;" placeholder="1.0" tabindex=6>
<input type="text" id="margin_bottom" class="paper_update" style="width: 50px; margin-right:20px;" placeholder=".5" tabindex=7>
<input type="text" id="margin_left" class="paper_update" style="width: 50px; margin-right:20px;" placeholder="1.0" tabindex=8>

Note: in order to create a cycling tabindex loop, start your first form element that you want to have focus at tabindex=2 instead of tabindex=1. Set your first and last tabindexes on spans or other elements that are outside of your desired loop.  For example, notice I set tabindex=1 and tabindex=11 to spans just before and after the loop. The reason for this will become apparent in the following steps.

Step 2: Add autofocus1 and autofocus2 classes to first and last elements of the loop

The text input box with the 8.5 in it is the first form element we want in our tabindex cycle, so in the text input tag, we need to add the class “autofocus1”.

The last text box in the form is the box we want to give the class “autofocus2”.  These classes will be used as targets in the next steps. When we get to the end of the tabindex series, we will change the focus to target the autofocus1 class and vice versa.

Step 3: Set onfocus=”document.querySelector(‘.autofocus2’).focus() on tabindex=1

In the span element just before the beginning of the loop cycle, which was set to tabindex=1, set an onfocus event and a JavaScript selector which will call a focus() function to change the focus back to class autofocus2.

<span class="paper_help_note" tabindex=1 onFocus="document.querySelector('.autofocus2').focus()">Paper size</span>

What this means is, if this span outside of my form gets focus due to a user using Shift + Tab on their keyboard, then cycle the focus back to the element that has the class “autofocus2”, which in this case is the last form element in the loop, which also has tabindex=10:

<input type="text" id="pages" class="paper_update autofocus2" style="width: 50px; margin-right:20px;" tabindex=10>

Step 4: Set onfocus=”document.querySelector(‘.autofocus1’).focus() on tabindex=11

Just like in Step 2, we want to set up another onfocus event that will trigger a change of focus, but this time set to tabindex=11 which is the span just passed the end of the tabindex loop.

<span class="paper_help_note" tabindex=11 onFocus="document.querySelector('.autofocus1').focus()"></span>

This means if this span outside of my form gets focus due to a user using Tab on their keyboard, then cycle the focus back to the element that has the class “autofocus1”, which in this case is the first form element in the loop, which has tabindex=2:

<input type="text" id="finished_size_width" class="paper_update autofocus1" style="width: 40px;" placeholder="8.5" tabindex=2 autofocus>

For more information about HTML5 autofocus, see:
https://www.w3schools.com/tags/att_input_autofocus.asp

For more information about the onfocus event, see:
https://www.w3schools.com/jsref/event_onfocus.asp
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onfocus

For more information about tabindex, see:
https://www.w3schools.com/tags/att_global_tabindex.asp
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex

For more information about focus(), see:
https://www.w3schools.com/jsref/met_html_focus.asp
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus