【Next.js】ハンバーガーメニューのアニメーション実装

公開日: 2026年9月12日 · 読了目安 9 分

Next.js でモバイルナビを開閉する手順。フォーカス閉じ込め、スクロールロック、オーバーレイの入場。完成ヘッダーを載せる判断も解説します。

先に結論:見た目より、閉じられることが先

ハンバーガーのアニメーションは、線がバツになる、パネルが右から出る、背景が暗くなる、の3点で十分です。先に必要なのは Escape で閉じる、フォーカスがパネル内に残る、背景がスクロールしない、です。

page.tsx はサーバーのまま、ヘッダーだけ "use client" にします。

作り方は3つです。CSS の開閉。Radix / vaul などのプリミティブ。完成しているナビを載せる。

使いにくいメニューになる3つの理由

1つ目は、開いたまま背面がスクロールすることです。body の overflow を開閉に合わせて切ります。

2つ目は、フォーカスが背面のリンクに逃げることです。

3つ目は、閉じる手段がハンバーガー再タップだけのことです。オーバーレイタップと Escape を足します。

方法1:状態と CSS で開閉する

useState で open を持ち、パネルに translate と opacity を付けます。ボタンには aria-expanded と aria-controls を付けます。

最小の開閉

components/MobileNav.tsx
"use client";

import { useState } from "react";

export function MobileNav() {
  const [open, setOpen] = useState(false);
  return (
    <div className="md:hidden">
      <button
        type="button"
        aria-expanded={open}
        onClick={() => setOpen((v) => !v)}
      >
        メニュー
      </button>
      {open ? (
        <nav className="fixed inset-0 z-50 bg-zinc-950/95 p-6">
          <a href="#pricing">料金</a>
        </nav>
      ) : null}
    </div>
  );
}

方法2:プリミティブに任せる

フォーカス閉じ込めとスクロールロックまで自分で書くと漏れます。Dialog 系のプリミティブを使うと、アニメーションだけ足せば足ります。

shadcn/ui の Sheet は、この用途に近いです。見た目の署名は、完成ナビの方が強いです。

方法3:完成しているヘッダーを載せる

デスクトップは透明の固定、モバイルはフルスクリーンの開閉、という塊は、ヘッダー記事の方法2とこの記事を足しても時間がかかります。

DesignLayer でライブプレビューし、リンクだけ差し替えてください。ヘッダー全体の解説は https://design-layer.com/articles/nextjs-modern-header-guide です。

無料コピーは1日3回です。ナビとヒーローを同じ日に取るなら、枠を計画してください。

公開前チェックリスト

1. Escape で閉じるか。2. 開いているとき背面がスクロールしないか。3. フォーカスリングが見えるか。4. md 以上でハンバーガーが消えるか。5. 動きを reduced-motion で弱められるか。

【Next.js】ハンバーガーメニューのアニメーション実装 | DesignLayer