「ここから出ないで!」モーダルのフォーカストラップを攻略しよう
Web制作を始めたばかりの頃、ふとこんな壁にぶつかったことはありませんか?
「モーダルウィンドウを作ったはいいけれど、キーボードで『Tab』キーを押すと、裏側のページまでフォーカスが飛んでいってしまう……」
これ、実は多くの初心者が通る「あるある」です。まるで、デパートの試着室に入ったのに、カーテンの隙間から店内に戻れてしまうような状態ですね。これを解決するのが、今回お話しする「フォーカストラップ」という考え方です。
今日は、インライン要素(`a`タグや`span`など)が混在するモーダルの中で、ユーザーを迷子にさせないための秘訣を、一緒に解き明かしていきましょう。
—
そもそも「フォーカストラップ」って何?
「ストラップ(trap)」=「罠」。つまり、「フォーカス(キーボードのカーソル位置)を、特定の範囲内から逃がさない」という仕組みのことです。
例えば、モーダルウィンドウが開いているとき。ユーザーは「この画面の中だけで操作を完結させる」ことを期待しています。それなのに、Tabキーを押すたびに画面外のリンクにフォーカスが当たってしまったら、「あれ、どこにいるの?」と混乱させてしまいますよね。
これを防ぐには、「最後の要素に行ったら、自動的に最初の要素へ戻す」という魔法(コード)をかけてあげる必要があるんです。
—
インライン要素が「悪さ」をするわけじゃない
よくある勘違いとして、「`a`タグや`strong`、`code`タグなどのインライン要素が悪いのでは?」と思う方がいますが、全くそんなことはありません。むしろ、これらはWebページの「構成要素」として欠かせない存在です。
問題は、「どれがフォーカスできる要素か?」をプログラムが判断できていないだけなのです。
フォーカスできる要素のリスト(これだけ覚えればOK!)
- `a`タグ(`href`属性があるもの)
- `button`タグ
- `input`、`select`、`textarea`などのフォーム部品
- `tabindex`属性が設定された要素
これら以外の `span` や `strong` は、基本的にキーボードでフォーカスできません。ですから、モーダルの中では「`a`タグや`button`だけを追いかけて、それ以外は無視する」というルールを作れば良いのです。
—
実装してみよう:小さな「輪っか」を作るイメージ
では、実際にJavaScriptで「フォーカスを閉じ込める」仕組みを作ってみましょう。
// モーダル内の「フォーカスできる要素」だけを抜き出すリスト
const modal = document.querySelector(‘.modal-container’);
const focusableElements = modal.querySelectorAll(‘a, button, input’);
// 最初の要素と最後の要素を取得
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length – 1];
// 「Tab」キーが押されたときの挙動を制御
modal.addEventListener(‘keydown’, (e) => {
if (e.key === ‘Tab’) {
// もし「Shift + Tab」で戻る時の処理
if (e.shiftKey) {
if (document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus(); // 最初に戻ったら、最後へ飛ばす
}
}
// 通常の「Tab」で進む時の処理
else {
if (document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus(); // 最後に行ったら、最初へ飛ばす
}
}
}
});
コードのポイント解説
1. `querySelectorAll`: ここで「モーダルの中にあるクリック可能なやつ全部!」と呼び集めています。
2. `e.preventDefault()`: これが重要です。「ブラウザのデフォルトの動き(次のリンクへの移動)を一時停止!」という指示です。これがないと、勝手にフォーカスが外へ逃げてしまいます。
3. `e.shiftKey`: 「Shift + Tab」を検知します。戻る操作の時も、ちゃんとループするようにケアしてあげるのが、優しいエンジニアの作法ですね。
—
焦らなくて大丈夫。まずは「動く」から始めよう
いかがでしたか? 最初は難しく感じるかもしれませんが、要は「モーダルの中という小さな部屋で、ユーザーが迷子にならないように入り口と出口を繋いでいるだけ」なんです。
- 「なぜフォーカスが外に飛ぶんだろう?」
- 「どうすれば閉じ込めることができるかな?」
そうやって一つずつ疑問を解決していく姿勢こそが、一流のエンジニアへの第一歩です。もし上手くいかなくても、まずは `console.log()` でどの要素にフォーカスが当たっているか確認するところから始めてみてください。
あなたの作るWebページが、誰にとっても「使いやすくて心地よい」ものになることを、心から応援しています!また分からないことがあれば、いつでも聞きに来てくださいね。

コメント