メガメニュー
ナビ項目にホバー/タップで複数列の大きなドロップダウンが開く。PCもスマホも対応。
プレビュー
ホバー
操作カーソルを乗せると動きます(スマホはタップ)。
仕様書
- 向く場面
- ECのカテゴリなど下層が多いナビ
- 列に分けて一覧を一望させたいメニュー
- PCホバーとスマホタップの両方に対応したい
- 避ける場面
- 下層が3〜4件しかない小さなメニュー
- モバイル幅で列が収まらない構成
- ホバーだけで開き外クリックで閉じない実装
- 構成要素
- ナビ
- トリガー
- パネル
- 列見出し
- リンク
- 持っている状態
- 通常
- ホバー
- 押下中
- キーボード
Tab でトリガーへ・Enter/Space で開閉・Tab でパネル内リンクへ移動(閉じたパネルのリンクには入らない)・Esc で閉じてトリガーへ戻る。外側クリックで閉じる
- 支援技術
トリガー button に aria-expanded/aria-haspopup/aria-controls を同期。閉状態のパネルは visibility:hidden で読み上げ・Tab から外れる。選んだリンクに aria-current=page
- 動き
パネル opacity と translateY 6px を 0.2s ease。ホバー離脱は 120ms 遅延で閉じ、隙間横断での誤閉じを防ぐ。reduced-motion では即時
デザインの要点
- ホバー離脱は 120ms 待ってから閉じる。トリガーとパネルの隙間を横切る一瞬で閉じると「掴めないメニュー」になる
- PC はホバー、タッチはタップでトグルと、pointerType で経路を分ける。タッチにホバーを当てると1回目のタップで開き2回目で遷移する
- 閉じたパネルは opacity:0 に visibility:hidden を重ねる。透明なだけのパネルは中のリンクに Tab が入り、見えない場所でフォーカスが迷子になる
- パネルは列ごとに見出しを立てる。20 件のリンクを一列に並べるより、3 列×見出しのほうが目の走査が速い
コード(コピーして使えます)
<div class="mm-root">
<header class="mm-header">
<span class="mm-logo">Shop</span>
<nav class="mm-nav">
<div class="mm-item">
<button class="mm-trigger" aria-expanded="false" aria-haspopup="true" aria-controls="mm-panel-1">カテゴリ ▾</button>
<div class="mm-panel" id="mm-panel-1">
<div class="mm-col">
<p class="mm-col-title">ファッション</p>
<a href="#">トップス</a>
<a href="#">ボトムス</a>
<a href="#">アウター</a>
</div>
<div class="mm-col">
<p class="mm-col-title">小物</p>
<a href="#">バッグ</a>
<a href="#">アクセサリー</a>
<a href="#">シューズ</a>
</div>
<div class="mm-col">
<p class="mm-col-title">特集</p>
<a href="#">セール</a>
<a href="#">新着</a>
<a href="#">ランキング</a>
</div>
</div>
</div>
<div class="mm-item">
<button class="mm-trigger" aria-expanded="false" aria-haspopup="true" aria-controls="mm-panel-2">ブランド ▾</button>
<div class="mm-panel" id="mm-panel-2">
<div class="mm-col">
<p class="mm-col-title">国内</p>
<a href="#">ブランドA</a>
<a href="#">ブランドB</a>
</div>
<div class="mm-col">
<p class="mm-col-title">海外</p>
<a href="#">ブランドC</a>
<a href="#">ブランドD</a>
</div>
</div>
</div>
</nav>
</header>
<div class="mm-body">
<p class="mm-hint">ナビをホバー/タップするとメニューが開きます</p>
</div>
</div>