テック技報最新号へ →
デザイン

ナビが実際に収まらなくなった時だけ、JSなしでドロワーメニューに切り替える(animation-timeline+スタイルクエリ)

ブレイクポイントで決め打ちせず、項目が溢れた瞬間に切り替わる。CMSで項目が増えても崩れない。

@tak_dcxi · 2026-10-17
#CSS#ナビゲーション#animation-timeline#スタイルクエリ#レスポンシブ#JSなし

どんな問題を解決するか / いつ使うか

グローバルナビを「768px以下ならハンバーガー」のように画面幅で切り替えると、項目の数や文字の長さが変わったときに、PC幅でも溢れたり、逆に余裕があるのにドロワーになったりする。項目数が運用で変わるサイト(CMS)のナビに使う。

仕組み

  1. ナビの項目リストを横スクロールできる箱にしておく。
  2. その箱に スクロール連動アニメーション(animation-timeline: scroll(...)) を付ける。スクロール連動のタイムラインは、中身が溢れてスクロールできるときにしか動かないので、「溢れているか」のフラグとして使える。アニメーションのキーフレームでカスタムプロパティ(例:--is-overflowing)を切り替える。
  3. 子の要素側で スタイルクエリ(@container style(--is-overflowing: ...)) を使って、フラグが立っていたらナビを隠し、ドロワーを開くボタンを出す。

コードの考え方(スケッチ)

css
/* 考え方のスケッチ。正確な実装は出典のCodePenを確認すること */
.nav-list {
  display: flex;
  overflow-x: auto;
  animation: detect-overflow linear both;
  animation-timeline: scroll(self inline); /* 溢れてスクロールできる時だけ有効 */
}
@keyframes detect-overflow {
  from, to { --is-overflowing: 1; }
}
/* スタイルクエリは「フラグを持つ要素の子孫」から問い合わせる */
@container style(--is-overflowing: 1) {
  .nav-list > li { visibility: hidden; } /* 場所は残すので、溢れの判定が消えない */
  .nav-list .drawer-button { visibility: visible; }
}

注意点

出典

X の元の投稿を開く