ご存じの方も多いかもしれませんが、WebサイトでTabキーを押下すると、ボタン・リンク・フォームコントロールなどに順番にフォーカスが当たります。 (Shiftキーを押したままTabキーを押すと、逆に辿る)
ここで問題になるのが、モバイルメニューなどのモーダルメニューを開いている時で、ユーザーとしてはモーダルメニュー内のリンクだけを辿りたいはずなので、裏側のコンテンツにフォーカスを当てる必要がありません。
ですが何も対策をしていないと、モーダルメニュー内の最後のメニューリンクを過ぎたらフォーカスが裏側のコンテンツに移動してしまって、「今どこにフォーカス当たってるんや!」「モーダルメニューにフォーカス戻すの大変やんけ!」とストレスを与えてしまいます。
これを解決するための理想的な挙動の一つとしては、以下のようなものかと思います。
- モバイルメニューを開いた直後は、閉じるボタンにフォーカスが当たっている事。
- モバイルメニューを開いている状態では、Tabキー(+Shiftキー)でのフォーカス移動をモバイルメニュー内の要素に限る事。
- モバイルメニュー内の最後の要素を過ぎたら、次のフォーカスはモーダルメニュー内の最初の要素に戻る事。逆に、最初の要素でTab+Shiftキーを押下した時(フォーカスを逆に辿る時)は、最後の要素にフォーカスを当てる事。
以上の要件を満たすためのjQueryを書いてみました。
$( function() {
// モーダルメニュー
var modalMenu = $( '#modal_menu' );
// モーダルメニューが開いているかどうか
var isOpenModalMenu;
// モーダルメニュー内でフォーカスを当てたい要素リスト
var modalMenuElements = modalMenu.find( 'a, button' );
// モーダルメニューを開く
$( '#open_modal' ).click( function() {
isOpenModalMenu = true;
$( '#close_modal' ).focus();
modalMenu.show();
});
// モーダルメニューを閉じる
$( '#close_modal' ).click( function() {
isOpenModalMenu = false;
modalMenu.hide();
});
// キーイベント
$( document ).keydown( function( event ) {
// モーダルメニューが開かれていた場合
if ( showDrawer ) {
// フォーカスが当たっている要素
var activeEl = document.activeElement;
// モーダルメニュー内でフォーカスを当てたい最初の要素
var firstEl = modalMenuElements[0];
// モーダルメニュー内でフォーカスを当てたい最後の要素
var lastEl = modalMenuElements[ modalMenuElements.length - 1 ];
// タブキーを押されたかどうか
var tabKey = ( 9 === event.keyCode );
// Shiftキーが押されているかどうか
var shiftKey = event.shiftKey;
// 最後の要素でタブキーが押された場合は、最初の要素にフォーカスを当てる
if ( ! shiftKey && tabKey && lastEl === activeEl ) {
event.preventDefault();
firstEl.focus();
}
// 最初の要素でタブキー+Shiftキーが押された場合は、最後の要素にフォーカスを当てる
if ( shiftKey && tabKey && firstEl === activeEl ) {
event.preventDefault();
lastEl.focus();
}
}
});
});
参考
Twenty Twenty(WordPress公式テーマ) https://github.com/WordPress/twentytwenty/blob/db82df5cb0293db15911b045471cee3f5f0ac389/assets/js/index.js#L442
※素のjavascriptをスラスラ書ける人は、こちらの方が参考になるかもしれません。