【完全保存版】CSSだけで作るハンバーガーメニュー実装|JavaScript不要でスマホ対応・横スクロール問題まで潰す

【完全保存版】CSSだけで作るハンバーガーメニュー実装|JavaScript不要でスマホ対応・横スクロール問題まで潰す

2025.12.21

はじめに|ハンバーガーメニュー、動くけど“地味に壊れる”のが怖い

スマホ対応のWebサイトで、ほぼ必須のUIがハンバーガーメニューです。

  • スマホでナビゲーションをどう出せばいい?
  • JavaScriptなしで実装できる?
  • CSSだけで本当に運用できる?

できます。できますが、作って終わりじゃないんですよね。

  • 開くけど背景が押せる(誤タップ祭り)
  • メニュー内がスクロールできない
  • 右から出したら横スクロールが出る(スマホ崩れ)
  • PC表示にしたら戻らない

私も昔、right:-100% で隠したつもりが、スマホだけ横スクロールが出て、
「え、メニュー閉じてるのに…?」ってなりました。
見た目は外にあるけど、レイアウト的には“はみ出し実体”が残ってたのが原因でした。

この記事は「ハンバーガーメニュー css」で検索してきた人向けに、
実装 → よくある事故の回避 → デバッグ手順までまとめた完全版です。


ハンバーガーメニューとは

ハンバーガーメニューは、三本線(≡)のアイコンをタップするとナビが出る仕組みです。

スマホで使われる理由は単純で、

  • 画面が狭いのでナビを常時置くと邪魔
  • でもナビは必要
  • なら隠しておいて必要な時だけ出す

という流れです。


CSSだけでハンバーガーメニューは作れる?

作れます。
基本はこの3点です。

  • チェックボックスで開閉状態を持つ
  • labelでタップ操作を作る
  • :checked を使って表示を切り替える

JavaScriptなしで「開く/閉じる」は成立します。

ただ、実務で使うなら最低限これも入れておくと安心です。

  • 背景クリック(タップ)で閉じる
  • メニュー内をスクロールできる
  • 横スクロール問題を起こしにくい隠し方
  • DevToolsで原因を特定できるセレクタ構造

まず動かす|基本HTML構造(おすすめ形)

最小構成でもいいんですが、運用で困りにくい形を最初から出します。
背景タップで閉じるために、オーバーレイも入れます。

<input type="checkbox" id="menu-toggle" class="menu-toggle">

<label for="menu-toggle" class="menu-btn" aria-label="メニューを開く">
  <span></span>
  <span></span>
  <span></span>
</label>

<label for="menu-toggle" class="menu-overlay" aria-hidden="true"></label>

<nav class="menu" aria-label="グローバルナビゲーション">
  <ul class="menu__list">
    <li><a href="#">ホーム</a></li>
    <li><a href="#">サービス</a></li>
    <li><a href="#">お問い合わせ</a></li>
  </ul>
</nav>

構造のポイント(ここがズレると動かない)

  • checkbox(menu-toggle)が開閉状態を持つ
  • menu-btn(label)をタップすると checked が切り替わる
  • overlay(label)も同じcheckboxに紐づける → 背景タップで閉じる
  • navがメニュー本体

ハンバーガーアイコンのCSS(3本線)

.menu-btn {
  width: 32px;
  height: 26px;
  display: inline-flex;
  flex-direction: column;
  justify-content: space-between;
  cursor: pointer;
}

.menu-btn span {
  display: block;
  height: 3px;
  background: #333;
  border-radius: 2px;
}

見た目はこれでOK。
(線を×に変えるアニメもできますが、まずは動作優先で進めます)


チェックボックスを“見えないけど使える”状態にする

display:none; でも動きますが、後で扱いづらくなることがあります。
見えない場所に置く形が無難です。

.menu-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

メニューを「横スクロール出にくい形」で隠す

ここが実務の差です。
right:-100% で隠すより、transformで画面外へ飛ばす方が事故りにくいです。

.menu {
  position: fixed;
  top: 0;
  right: 0;
  width: min(80vw, 360px);
  height: 100svh;
  background: #fff;

  transform: translateX(100%);
  transition: transform 0.3s ease;

  z-index: 1001;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.menu-toggle:checked ~ .menu {
  transform: translateX(0);
}

ここが効く理由(かみ砕き)

  • 見た目だけじゃなく、動きも安定する
  • 画面外に“実体”が残りにくい
    → 横スクロール問題・スマホ崩れが起きにくい

背景クリックで閉じる(オーバーレイ)

背景が押せる問題は、これでほぼ消えます。

.menu-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);

  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;

  z-index: 1000;
}

.menu-toggle:checked ~ .menu-overlay {
  opacity: 1;
  pointer-events: auto;
}

overlayがlabelなので、タップするとチェックが外れて閉じます。
JavaScriptなしで「背景タップで閉じる」が作れます。


左から出るハンバーガーメニューにする

右→左は、transform方向を変えるだけです。

.menu {
  left: 0;
  right: auto;
  transform: translateX(-100%);
}

.menu-toggle:checked ~ .menu {
  transform: translateX(0);
}

レスポンシブ対応(PCでは通常ナビに戻す)

「スマホだけハンバーガー、PCは横並びナビ」が定番です。

@media (min-width: 769px) {
  .menu-btn,
  .menu-overlay {
    display: none;
  }

  .menu {
    position: static;
    transform: none;
    height: auto;
    width: auto;
    overflow: visible;
    transition: none;
    z-index: auto;
  }
}

よくあるトラブルと対処(“あるある”だけ厳選)

メニューが表示されない

だいたいこのどれかです。

  • HTMLの並び順が違う(checkboxより後ろにmenuが無い)
  • セレクタが合ってない(+~ を勘違い)
  • そもそもcheckedになってない(labelのforが違う)

DevToolsでの確認手順(これが一番早い)

  1. F12 → Elements
  2. <input id="menu-toggle"> を選択
  3. checked が付くか確認(クリックでも付けられる)
  4. .menu を選択
  5. Stylesで transform が当たってるか見る(打ち消し線が出ていないか)

「checkedは付くのに動かない」なら、ほぼセレクタかHTML順です。


メニュー内がスクロールできない

項目が多いサイトで起きます。

.menu {
  overflow-y: auto;
  height: 100svh;
}

背景がクリックできてしまう

overlayを入れて、z-indexを整えます。
この記事の構成は、overlayが背景をブロックする作りです。


横スクロールが出る(スマホ崩れ)

原因として多いのはこれです。

  • right:-100% で隠して“はみ出し実体”が残る
  • 100vw を多用して微妙にオーバー
  • メニュー内の長い英数字が折り返されない

長い文字の対策

.menu a {
  overflow-wrap: anywhere;
}

CSSハンバーガーメニューのメリット・デメリット

メリット

  • JavaScript不要で軽い
  • 実装がシンプル
  • LPや小規模サイトなら十分運用できる

デメリット

  • フォーカス制御(キーボード操作の細かい配慮)は限界がある
  • aria-expandedの切り替えなど、状態に合わせた属性更新はCSSだけだとできない

「まず動く」「事故りにくい」を優先するならCSSのみでOK。
アクセシビリティをしっかり詰める段階になったら、JavaScript併用も検討する、でバランスが取れます。


まずはこれでOK|コピペ用まとめコード

HTML

<input type="checkbox" id="menu-toggle" class="menu-toggle">

<label for="menu-toggle" class="menu-btn" aria-label="メニューを開く">
  <span></span><span></span><span></span>
</label>

<label for="menu-toggle" class="menu-overlay" aria-hidden="true"></label>

<nav class="menu" aria-label="グローバルナビゲーション">
  <ul class="menu__list">
    <li><a href="#">ホーム</a></li>
    <li><a href="#">サービス</a></li>
    <li><a href="#">お問い合わせ</a></li>
  </ul>
</nav>

CSS(右からスライド)

.menu-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.menu-btn {
  width: 32px;
  height: 26px;
  display: inline-flex;
  flex-direction: column;
  justify-content: space-between;
  cursor: pointer;
}

.menu-btn span {
  display: block;
  height: 3px;
  background: #333;
  border-radius: 2px;
}

.menu-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  z-index: 1000;
}

.menu {
  position: fixed;
  top: 0;
  right: 0;
  width: min(80vw, 360px);
  height: 100svh;
  background: #fff;
  transform: translateX(100%);
  transition: transform 0.3s ease;
  z-index: 1001;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.menu-toggle:checked ~ .menu-overlay {
  opacity: 1;
  pointer-events: auto;
}

.menu-toggle:checked ~ .menu {
  transform: translateX(0);
}

.menu a {
  overflow-wrap: anywhere;
}

@media (min-width: 769px) {
  .menu-btn,
  .menu-overlay {
    display: none;
  }

  .menu {
    position: static;
    transform: none;
    height: auto;
    width: auto;
    overflow: visible;
    transition: none;
    z-index: auto;
  }
}

まとめ|CSSだけでも“実務で困りにくい”ハンバーガーメニューは作れる

CSSだけで作るなら、ポイントはこれです。

  • checkbox+labelで開閉状態を持つ
  • transformで隠して横スクロール問題を起こしにくくする
  • overlayで背景タップ閉じ&誤操作防止
  • overflowでメニュー内スクロール
  • DevToolsでcheckedと打ち消し線を見て原因を切り分ける

「ハンバーガーメニュー css」で探しているなら、
まずはこの記事の基本形をコピペして動かしてみてください。
動いたら、幅・色・アニメ・配置をサイトに合わせて整えるだけです。

タグ:

#CSS #HTML #ハンバーガーメニュー css #スマホ対応 #レスポンシブ #スライドメニュー #横スクロール #アクセシビリティ