HTMLタグのtabindex属性が同じ値同士の要素はTABキーによるフォーカス送りが該当要素内で順に行われるので、グループ化したい要素にそれぞれ同じ値のtabindexを振り、それぞれのグループ内での先頭または終端の要素にフォーカスが当たっている際にTABキーまたはSHIFT+TABキーが押下された際には逆側の末端の要素にフォーカスを移動させることで、グループ内でフォーカス移動がループするようにしています。
動作デモ
マウスポインタで適当な要素を選択したあとは、その要素が属するグループ内でTABキーまたはSHIFT+TABキーによるフォーカス移動がループします。
sample.html
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title>tabIndexGroup</title>
<style>
input[type=text] {
width: 80px;
}
</style>
</head>
<body>
<input type='text' class='group1' placeholder='A'>
<input type='text' class='group1' placeholder='A'>
<input type='text' class='group1' placeholder='A'>
<input type='checkbox' class='group1' placeholder='A'>
<button class='group1'>A</button><br><br>
<input type='text' class='group2' placeholder='B'>
<input type='text' class='group2' placeholder='B'>
<input type='text' class='group2' placeholder='B'>
<input type='checkbox' class='group2' placeholder='B'>
<button class='group2'>B</button><br><br>
<input type='text' class='group3' placeholder='C'>
<input type='text' class='group3' placeholder='C'> 
<input type='text' class='group4' placeholder='D'>
<input type='text' class='group4' placeholder='D'><br>
<input type='text' class='group3' placeholder='C'>
<input type='text' class='group3' placeholder='C'> 
<input type='text' class='group4' placeholder='D'>
<input type='text' class='group4' placeholder='D'>
<script>
'use strict';
const setTabIndex = cssSelector => {
const targetElements = document.querySelectorAll(cssSelector);
const lastIndex = targetElements.length - 1;
const newTabIndex = Math.max(...[...document.querySelectorAll('*')].map(e => e.tabIndex)) + 1;
targetElements.forEach(e => e.tabIndex = newTabIndex);
document.addEventListener('keydown', e => {
if(e.key !== 'Tab') return;
if(e.target === targetElements[e.shiftKey ? 0 : lastIndex]) {
e.preventDefault();
targetElements[e.shiftKey ? lastIndex : 0].focus();
}
});
};
setTabIndex('.group1');
setTabIndex('.group2');
setTabIndex('.group3');
setTabIndex('.group4');
</script>
</body>
</html>
MDNによると、tabindexの値に0より大きな値を使用することは以下の理由から避けるべきである旨の説明があるので、乱用はしないほうが良いかもしれません。
tabindex の値に 0 よりも大きな値を使用することは避けてください。そうすると、支援技術に頼っている人がページコンテンツを移動したり操作したりすることが難しくなります。代わりに、論理的な順序で要素を並べて文書を書いてください。