目次
- はじめに|ハンバーガーメニュー、動くけど“地味に壊れる”のが怖い
- ハンバーガーメニューとは
- CSSだけでハンバーガーメニューは作れる?
- まず動かす|基本HTML構造(おすすめ形)
- 構造のポイント(ここがズレると動かない)
- ハンバーガーアイコンのCSS(3本線)
- チェックボックスを“見えないけど使える”状態にする
- メニューを「横スクロール出にくい形」で隠す
- ここが効く理由(かみ砕き)
- 背景クリックで閉じる(オーバーレイ)
- 左から出るハンバーガーメニューにする
- レスポンシブ対応(PCでは通常ナビに戻す)
- よくあるトラブルと対処(“あるある”だけ厳選)
- メニューが表示されない
- DevToolsでの確認手順(これが一番早い)
- メニュー内がスクロールできない
- 背景がクリックできてしまう
- 横スクロールが出る(スマホ崩れ)
- 長い文字の対策
- CSSハンバーガーメニューのメリット・デメリット
- メリット
- デメリット
- まずはこれでOK|コピペ用まとめコード
- HTML
- CSS(右からスライド)
- まとめ|CSSだけでも“実務で困りにくい”ハンバーガーメニューは作れる
はじめに|ハンバーガーメニュー、動くけど“地味に壊れる”のが怖い
スマホ対応の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での確認手順(これが一番早い)
- F12 → Elements
<input id="menu-toggle">を選択- checked が付くか確認(クリックでも付けられる)
.menuを選択- 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」で探しているなら、
まずはこの記事の基本形をコピペして動かしてみてください。
動いたら、幅・色・アニメ・配置をサイトに合わせて整えるだけです。