CSS の focus-within 擬似クラスによるドロップダウンメニュー

hover 擬似クラスを使用して、ドロップダウンメニュー (プルダウンメニュー) の表示・非表示を制御する方法はよく知られていますが、hover 擬似クラスはスマホやタブレットなどのタッチデバイスとの相性は良くありません。

そこで、今回は hover 擬似クラスではなく、focus-within 擬似クラスでドロップダウンメニューを制御する方法をご紹介します。

hover 擬似クラスのおさらい

よくある hover 擬似クラスを使用したドロップダウンメニューの HTML と CSS は次のようなものです。

…
<style>
.__menu_sub {
  /* 表示時の設定 */
}
.__menu_item:not(:hover) > .__menu_sub {
  /* 非表示時の設定 */
}
</style>
…
<ul class="__menu">
  <li class="__menu_item">メニューの項目1
    <ul class="__menu_sub">
      <li><a href="…">サブメニューの項目1</a></li>
      <li><a href="…">サブメニューの項目2</a></li>
    </ul>
  </li>
  <li class="__menu_item">メニューの項目2
    <ul class="__menu_sub">
      <li><a href="…">サブメニューの項目1</a></li>
      <li><a href="…">サブメニューの項目2</a></li>
    </ul>
  </li>
</ul>
…

親要素が hover 状態でなければ、その子要素を非表示にするという設定ですね。

focus-within 擬似クラスのおさらい

focus-within 擬似クラスは Selectors Level 4 で追加された、比較的新しい擬似クラスです。要素そのものか、その子孫要素が focus 状態にある場合にマッチします。

先程の CSS コードに focus-within 擬似クラスを追加すると、キーボードのタブ移動にも対応したドロップダウンメニューが出来上がります。

.__menu_item:not(:hover, :focus-within) > .__menu_sub {
  /* 非表示時の設定 */
}

focus-within 擬似クラスによるドロップダウンメニュー

focus-within 擬似クラスを使用してドロップダウンメニューを制御する場合、クリック (タップ) によって focus 状態になる要素が必要になります。ここでは button 要素をします。

…
<style>
.__menu_sub {
  /* 表示時の設定 */
}
.__menu_item:not(:focus-within) > .__menu_sub {
  /* 非表示時の設定 */
}
</style>
…
<ul class="__menu">
  <li class="__menu_item">
    <button type="button" class="__menu_button">メニューの項目1</button>
    <ul class="__menu_sub">
      <li><a href="…">サブメニューの項目1</a></li>
      <li><a href="…">サブメニューの項目2</a></li>
    </ul>
  </li>
  <li class="__menu_item">
    <button type="button" class="__menu_button">メニューの項目2</button>
    <ul class="__menu_sub">
      <li><a href="…">サブメニューの項目1</a></li>
      <li><a href="…">サブメニューの項目2</a></li>
    </ul>
  </li>
</ul>
…

button 要素をクリック (タップ) すると focus 状態になるので、その親要素が focus-within にマッチし、ドロップダウンメニューが表示されるという仕組みです。

複数の要素が focus 状態になることはありません。

異なる button 要素をクリック (タップ) すると、その button 要素が focus 状態になり、新たにドロップダウンメニューが表示され、それまで表示されていたドロップダウンメニューは非表示になります。これは、タブメニューに似た挙動ですね。

button 要素以外の場所をクリック (タップ) すると、focus 状態が解除されるため、表示されていたドロップダウンメニューは非表示になります。これは、ポップアップウィンドウに似た挙動ですね。

つまり、タブメニューとポップアップウィンドウを掛け合わせたドロップダウンメニューになります。

CodePen

See the Pen Dropdown menus using :focus-within by nov (@numerofive) on CodePen.

夏が終わる。

関連記事