擬似要素 focus-within を使う時に気を付けること

最終更新日: 公開日: 2022年08月

先日,「キーボードナビゲーションの実現」という記事を投稿した後に気づいたのだが,擬似要素 focus-within を使って,ドロップダウンメニューを制御すると問題があることが判明した.
条件は少し限定されるが,それはドロップダウンメニューの作成の際に親カテゴリーがクリックできればよいのだが,クリック出来ない親カテゴリーがあった場合の話である.

キーボードナビゲーション
タブキーだけでメニューを移動しているところ

「ちょっと何言っているか分からない」という人も多いと思うので,「キーだけでホームページを閲覧する」部分はその投稿をみてください.

ドロップダウンメニューに関する不具合

リンクのないメニューをクリックするとドロップダウンメニューが表示されっぱなし状態

focus-within というのはその要素の子孫まで含めてフォーカスが当たった時という判定ができる便利な擬似要素なのだが,クリックしてしまうと次に別の要素をクリックするまではずっとフォーカスが当たった状態になる.
つまり,ドロップダウンメニューの表示を focus-within を使って行うとマウスでクリックした時に表示されっぱなしになってしまうのだ.
通常,マウスカーソルが上に乗った時だけ(hover)ドロップダウンメニューが出てほしいので,hover を使うのだが,focus-within も追加で定義してしまうとクリックでフォーカスが機能してしまい,メニューが出っぱなし状態になる.

focus-within 以外に何か良い方法はないか考えたのだが,思いつかない.

クリック出来ないようにすればよい

ふと,これ,「そもそもクリックできるのがまずいのでは?」と気が付いた.
元々,A タグではなかったのだが,キーボードナビゲーションのために A タグにして,さらに tabindex="0" したのである.なぜ,tabindex を 0 にしたのかは先ほどのナビゲーションのページをみてください.

A タグだとhref があろうがなかろうがクリックできる状態になってしまう.タブキーで飛べるように tabindex を設定したが,クリックはできてしまう.

そこで,pointer-events: none; を使う.

タブキーで飛べるけどクリックは出来ないようにする

クリック出来ない設定を tabindex="0" に適用

まず,クリック出来ない親カテゴリーを持つドロップダウンメニューの HTML は以下のようになっている.(チェックボックスの input タグとかは省略している.)

<li>
  <a tabindex="0">クリックできない親カテゴリー</a>
  <ul>
    <li><a href="xxxx">子ページ</a></li>
    <li><a href="yyyy">子ページ2</a></li>
  </ul>
</li>

CSS では以下のように tabindex="0" の Aタグリンクだけクリック無効とする.

li a[tabindex="0"] {
  pointer-events: none;
}

こうするとキーボードだけでの移動でドロップダウンメニューの表示も出来て,ドロップダウンメニュー内もタブキーで移動することが出来る.
さらにマウスでクリックしたとしても,ドロップダウンメニューが表示されっぱなしにはならない.

擬似要素 focus-within を hover の代わりに使う時

まとめると,擬似要素 focus-within を hover の代わりに使うのはキーボードナビゲーションを実現するためだと思うが,その際,クリックで思った通りの動作をしないようになるなら,クリックをそもそもさせない pointer-events: none; を使おうという話でした.

 

Contact

ご質問等ありましたら,お手数ですが弊社の個人情報保護方針をお読み頂いた上でフォームからお願い致します.

 
   
contact
Pagetop