htmltabstabindex

Keep focus looping on inputs of form when using tab instead of moving to second form


I want to restrict the focus to a single form when tab is pressed.
By that I mean focus on form 1's tab index 1, 2, and 3, and then move back to 1 within the same form, then 2, etc., never going to form 2's inputs. I also don't want to change the tab indices.

<form style="background-color:red">
    <input tabindex="01"/>
    <input tabindex="02"/>
    <input tabindex="03"/>
</form>

<form style="background-color:blue">
    <input tabindex="01"/>
    <input tabindex="02"/>
    <input tabindex="03"/>
</form>

Solution

  • This isn't good practice, so don't do it unless there is really good reason to do it...


    But there's no built in HTML way to do this, so we need to use some JavaScript along with a custom data attribute.

    I think it's easiest to use a data attribute to the parent (the <form>) so that way we don't have to add it to each input individually. I named mine data-tabgroup.

    Then we need some JS:

    // Select the tab groups based on the data attribute we added
    var tabgroups = document.querySelectorAll("[data-tabgroup]");
    
    // Loop through each to attach the listeners we need
    for (var i = 0; i < tabgroups.length; i++) {
      var inputs = tabgroups[i].querySelectorAll("[tabindex]");
    
      // Loop through all of the elements we want the tab to be changed for
      for (var j = 0; j < inputs.length; j++) {
    
        // Listen for the tab pressed on these elements
        inputs[j].addEventListener("keydown", function(myIndex, inputs, e) {
          if (e.key === "Tab") {
            // Prevent the default tab behavior
            e.preventDefault();
    
            // Focus the next one in the group
            if (inputs[myIndex + 1]) {
              inputs[myIndex + 1].focus();
            } else { // Or focus the first one again
              inputs[0].focus();
            }
          }
        }.bind(null, j, inputs)) // Make a copy of the variables to use in the addEventListener
      }
    }
    <form style="background-color: red" data-tabgroup>
      <input tabindex="01" />
      <input tabindex="02" />
      <input tabindex="03" />
    </form>
    
    <form style="background-color: blue" data-tabgroup>
      <input tabindex="01" />
      <input tabindex="02" />
      <input tabindex="03" />
    </form>

    And that's it! Here's the demo.


    Some notes: