目次
- はじめに|スマホメニュー、作るのは簡単。でも“運用で壊れやすい”
- スマホメニューとは何か
- なぜスマホ専用メニューが必要なのか
- CSSだけでスマホメニューは作れる?
- まず動かす|スマホメニューの基本構造(HTML)
- ポイント(ここを外すと動かない)
- ハンバーガーボタンのCSS(三本線)
- checkboxは「display:none」より安全に隠す
- メニューを初期状態で隠す(横スクロールが出にくい方法)
- クリックでメニューを表示する(checkedで切り替え)
- 仕組み(かみ砕き)
- 背景タップで閉じる(オーバーレイを出す)
- 左からスライドするスマホメニューにする
- レスポンシブ対応(PCでは通常ナビに戻す)
- スマホメニューでよくあるトラブルと解決
- メニューが閉じない/開かない
- DevToolsでの確認手順
- メニュー内がスクロールできない
- 背景がクリックできてしまう
- 横スクロールが出る(スマホ崩れ)
- CSSだけのスマホメニューのメリット・デメリット
- メリット
- デメリット
- まずはこれでOK|コピペ用まとめコード
- HTML
- CSS(右からスライド)
- まとめ|スマホメニューは「仕組み+事故対策」で完成度が上がる
はじめに|スマホメニュー、作るのは簡単。でも“運用で壊れやすい”
スマホ対応のWebサイトを作るとき、ほぼ必ず必要になるのが「スマホ用メニュー」です。
- スマホでナビゲーションをどう表示すればいい?
- ハンバーガーメニューをCSSだけで作れる?
- JavaScriptは使わないとダメ?
作れます。
ただ、動くだけだとあとで困りがちです。
- 開くけど背景が押せる(誤タップ)
- メニュー内がスクロールできない
- スライドさせたら横スクロールが出る(スマホ崩れ)
- PC表示に戻したらメニューが変な位置のまま
私も昔、right:-100% で隠したメニューが原因で、スマホだけ横スクロールが出て焦りました。
見た目は隠れてるのに「画面外に実体が残ってる」状態だったんですよね。
この記事では「スマホ メニュー css」で検索してきた人向けに、
CSSだけで実装しつつ、事故りやすいポイントを最初から潰す作り方をまとめます。
スマホメニューとは何か
スマホメニューは、スマートフォン表示時に使われるナビゲーションのことです。
よくある形はこの3つ。
- ハンバーガーメニュー(≡)
- スライドメニュー(右/左から出る)
- フルスクリーンメニュー(画面を覆う)
この中で一番使われるのがハンバーガーメニュー。
見た目がスッキリするし、実装も軽めです。
なぜスマホ専用メニューが必要なのか
PC用ナビをそのままスマホに持ってくると、
- 横幅に収まらない
- 文字が小さくて押しづらい
- 画面がごちゃごちゃする
が起きます。
だからスマホは「折りたたみ」が基本になります。
CSSだけでスマホメニューは作れる?
作れます。
ポイントはこれだけです。
- checkboxで「開いてる/閉じてる」を持つ
- labelでタップ操作を作る
:checkedで表示を切り替える
ただ、実務で困りにくい形にするなら追加でこれも入れます。
- 背景タップで閉じる(オーバーレイ)
- メニュー内スクロール
- 横スクロール問題が出にくい隠し方(transform)
- DevToolsで原因が追いやすいセレクタ設計
まず動かす|スマホメニューの基本構造(HTML)
最小構成より、運用で困りにくい形を最初から置きます。
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" class="menu-button" 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-button(label)を押すとcheckedが切り替わる
- overlayもlabelにして背景タップで閉じる
- checkboxより後ろにmenuがある(
~セレクタで効かせる)
ハンバーガーボタンのCSS(三本線)
.menu-button {
width: 32px;
height: 26px;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
cursor: pointer;
}
.menu-button span {
display: block;
height: 3px;
background: #333;
border-radius: 2px;
}
checkboxは「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;
}
クリックでメニューを表示する(checkedで切り替え)
.menu-toggle:checked ~ .menu {
transform: translateX(0);
}
仕組み(かみ砕き)
- checkboxがcheckedになる
- checkedのときだけmenuのtransformを0にする
- transitionでスライドして見える
背景タップで閉じる(オーバーレイを出す)
背景が触れると、ユーザーは迷います。
オーバーレイを入れて、タップで閉じられるようにします。
.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なので、タップするとcheckedが外れて閉じます。
JavaScriptなしで「背景タップ閉じ」が完成します。
左からスライドするスマホメニューにする
右→左は、transform方向を変えるだけです。
.menu {
left: 0;
right: auto;
transform: translateX(-100%);
}
.menu-toggle:checked ~ .menu {
transform: translateX(0);
}
レスポンシブ対応(PCでは通常ナビに戻す)
スマホ専用にしたいなら、ここを入れます。
@media (min-width: 769px) {
.menu-button,
.menu-overlay {
display: none;
}
.menu {
position: static;
transform: none;
height: auto;
width: auto;
overflow: visible;
transition: none;
z-index: auto;
}
}
スマホメニューでよくあるトラブルと解決
メニューが閉じない/開かない
原因はだいたいこれです。
for="menu-toggle"とid="menu-toggle"が合ってない- セレクタが合ってない(
+と~を混同) - HTMLの並び順が違う(checkboxより前にmenuがある)
DevToolsでの確認手順
- F12 → Elements
#menu-toggleを選択- checked が付くか見る(クリックでも付く)
.menuを選択- Stylesで
transformが当たっているか確認(打ち消し線が出ていないか)
checkedは付くのに動かないなら、ほぼセレクタか並び順です。
メニュー内がスクロールできない
.menu {
overflow-y: auto;
height: 100svh;
}
これで解決することが多いです。
背景がクリックできてしまう
- overlayを入れる
- z-indexをmenuより一段下にする
この記事の構成なら、背景は基本触れません。
横スクロールが出る(スマホ崩れ)
原因はこの辺が多いです。
100vwの使いすぎright:-100%系の隠し方で画面外に実体が残る- 長い英数字が折り返されない
長い文字の対策はこれ。
.menu a {
overflow-wrap: anywhere;
}
CSSだけのスマホメニューのメリット・デメリット
メリット
- JavaScript不要で軽い
- 実装がシンプル
- 小規模サイト・LPなら十分運用できる
デメリット
- フォーカス制御など細かいアクセシビリティ対応は限界がある
- aria-expandedの切り替えなど「状態に合わせた属性更新」はCSSだけでは難しい
まずはCSSで組んで、必要になったらJavaScriptを足す。
この順番が一番ラクです。
まずはこれでOK|コピペ用まとめコード
HTML
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" class="menu-button" 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-button {
width: 32px;
height: 26px;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
cursor: pointer;
}
.menu-button 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-button,
.menu-overlay {
display: none;
}
.menu {
position: static;
transform: none;
height: auto;
width: auto;
overflow: visible;
transition: none;
z-index: auto;
}
}
まとめ|スマホメニューは「仕組み+事故対策」で完成度が上がる
CSSだけでもスマホ用メニューは作れます。
ただ、実務で困らない形にするなら、ここがポイントです。
- checkbox+labelで開閉
- transformで隠して横スクロール問題を回避しやすくする
- overlayで背景タップ閉じ&誤タップ防止
- overflowでメニュー内スクロール
- DevToolsでcheckedと打ち消し線を見て原因を切り分ける
「スマホ メニュー css」で探しているなら、
まずはこの記事の基本形をコピペして動かしてみてください。
動いたら、配色や幅、ボタンの位置をサイトに合わせて整えるだけです。