モーダル作成の際に気をつけたいfocus()の基本
※本ブログの目的は個人の備忘録であり、コードは参考用として掲載しています。
実際に使用される際は、ご自身の環境で十分に動作確認を行ってください。
コードの利用によって生じたいかなる問題についても責任を負いかねますので、あらかじめご了承ください。
はじめに
Web制作でフォームやモーダルを扱うとき、JavaScriptのfocus()を使って特定の要素にフォーカスを当てることがよくあります。
しかし、CSSで非表示にしている要素に対してfocus()を呼んでも効かないケースがあります。
この記事では、focus()の基本、visibility: hiddenなどの非表示スタイルとの関係、そしてフォーカストラップの実装ポイントについて解説します。
focus()の基本
JavaScriptのfocus()は、対象の要素にフォーカスを移動させるメソッドです。
例えば、ページが読み込まれたときに検索フォームへ自動的にカーソルを移動したいときに使います。
<input type="text" id="search" placeholder="検索..." />
<script>
window.addEventListener("load", () => {
document.getElementById("search").focus();
});
</script>非表示要素とfocus()
display: none と visibility: hiddenが適用されている場合focus()が効かない
display: none… 要素自体がDOMツリー上には存在するが、描画・レイアウトから完全に外れる。visibility: hidden… 要素のスペースは確保されるが、見えない状態になる。
いずれの場合も「ユーザーに操作できない要素」とみなされるため、focus()を実行しても反応しません。
<input type="text" id="hiddenInput" style="visibility: hidden;" />
<script>
document.getElementById("hiddenInput").focus(); // 効かない
</script>モーダルを表示した際、その表示方法がvisibility: hiddenを利用したcssアニメーションでtransitionをかけている場合、要素がvisibility: visibleになっていないとfocus()が効きません。
setTimeoutなどを利用して少しずらしてからfocus()するなど、対策を取りましょう。
逆に言えば、モーダルを表示していないときはvisibility: hidden を指定してフォーカスが当たらないようにしておくべきである、とも言えるでしょう。
フォーカスできる要素とtabindexの活用
focus() は どんな要素にでも効くわけではありません。デフォルトでフォーカスできるのはリンクやボタン、フォームの要素などに限られます。
以下は代表的な例です。
<a href="..."><button><input>,<textarea>,<select><iframe>
一方で、ただの <div> や <span> に focus() を呼んでも反応しません。
しかし、tabindex 属性を付けることで任意の要素をフォーカス可能にできます。
tabindex="0"では、ユーザーが Tab キーで移動できるようになります。
<div id="box" tabindex="0">ここにフォーカスできます</div>
<script>
document.getElementById("box").focus(); // OK
</script>また、tabindex="-1"ではタブ移動ではフォーカスしません。しかし、focus()することは可能です。
タブ移動ではフォーカスさせたくない場合などに便利です。
例えば、フォームのエラーが出た場合、エラーメッセージの要素に tabindex="-1" を付けて focus() すると、タブで移動していなくてもエラー部分にフォーカスが当たり、タブ利用者に親切です。
ただし、無闇にtabindexを付けてフォーカス可能にすると逆にユーザーが迷うので、必要な場面だけに限定したほうがよいでしょう。
まとめ
focus()は特定の要素にフォーカスを移す便利なメソッドですが、display: noneやvisibility: hiddenが付いた非表示要素には効きません。
デフォルトでフォーカス可能なのはリンクやボタン、フォーム系要素などに限られますが、tabindexを使うことで任意の要素にもフォーカスを当てることができます。
特にtabindex="-1"はタブキーでは飛ばされませんが、JavaScriptからのfocus()が可能なため、モーダルの初期フォーカスやフォームエラー表示などに役立ちます。必要な場面だけに限定して使うのがポイントです。
アクセシビリティを考慮したモーダルを作成する際は、これらの点に気をつけてみてください。