How to separate keyboard tabbing rotation group without JavaScript?

Viewed 173

We can use Tab key in the keyboard to cycle fucus on inputs and buttons.

We can also use Space key to kinda click on a button when one is on focus.

Take the demo below for example, if you press Tab multiple times, you will cycle through the inputs, and when you press Space when the <button>Popup</button> is on focus, you will see a popup with another two buttons.

Now, when you keep pressing Tab, you will see the focus cycle outside of the popup.

popup.addEventListener('click', function(){
  overlay.classList.add('active');
});

overlay.addEventListener('click', function(e){
  if (e.target === overlay)
    overlay.classList.remove('active');
});
input {
  display: block;
}

input:nth-child(3){
  display: inline-block;
}

button {
  margin: 0 0.25em;
}

#overlay {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.25);
  display: none;
}

#overlay.active {
  display: flex;
  justify-content: center;
  align-items: center;
}

#container {
  width: 300px;
  background-color: #fff;
  padding: 1em;
  display: flex;
  justify-content: flex-end;
}
<input>
<input>
<input><button id="popup">Popup</button>
<input>
<input>

<div id="overlay">
  <div id="container">
    <button>Cancel</button>
    <button>OK</button>
  </div>
</div>

Is there a built-in way to bound the cycle group within a defined scope (i.e., parent element) so that the tabbing will only cycle through the sibling elements?

Edit

I know how to do it with JavaScript, but it feels overly complicated for a seemingly simple functionality. So I'm kinda looking for a non-JS alternative (i.e., HTML built-in attribute, CSS properties) or a JS solution (not jQuery) that relates to maybe a built-in HTMLElement properties that I haven't heard of.

1 Answers

Yes, this is an example of HTML with simple Javascript events attached. I still use your example code with the button event so thats why there is separate JS, but all logic is in the html.

popup.addEventListener('click', function(){
  overlay.classList.add('active');
});

overlay.addEventListener('click', function(e){
  if (e.target === overlay)
    overlay.classList.remove('active');
});
input {
  display: block;
}

input:nth-child(3){
  display: inline-block;
}

button {
  margin: 0 0.25em;
}

#overlay {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.25);
  display: none;
}

#overlay.active {
  display: flex;
  justify-content: center;
  align-items: center;
}

#container {
  width: 300px;
  background-color: #fff;
  padding: 1em;
  display: flex;
  justify-content: flex-end;
}
<span tabindex=1 onFocus="document.querySelector('.autofocus2').focus()">Top cycke</span>
<input class="autofocus1" tabindex="2" autofocus="">
<input  tabindex="3">
<input  tabindex="4">
<button id="popup"  tabindex="5">Popup</button>
<input  tabindex="9">
<input  tabindex="10">

<div id="overlay">
  <div id="container">
    <span autofocus="" onFocus="document.querySelector('.innerautofocus2').focus()"></span>
    <button  tabindex="6" class="innerautofocus1">Cancel</button>
    <button tabindex="7" class="innerautofocus2" >OK</button>
    <span tabindex="8" onFocus="document.querySelector('.innerautofocus1').focus()">   </span>
  </div>
</div>

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

The behavior as follows: The HTML autofocus even triggers focus on the first item with tabindex 2. Subsequent tabs will loop through all tabindexes in order, skipping hidden options. As you see without the popup box, indexes 6-8 are skipped. When it reaches the end, autofocus triggers a new focus set on the first item in the list.

With the popup box active, a new set of autofocus triggers set the inner loop of tabs with the same logic as above

Related