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

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

2025.12.21

はじめに|スライドメニュー、作ったのに「なぜかズレる」問題

スマホ対応のWebサイトを作るとき、
ハンバーガーメニューとセットでよく使うのが「スライドメニュー」です。

  • 右や左からメニューがスーッと出てくる
  • 画面を広く使えて操作しやすい
  • JavaScriptなしでも形になる

…なんですが、実際に作ると、妙な事故が起きます。

  • メニューが出ない(セレクタが合ってない)
  • 出るけど背景が押せる(z-indexが足りない)
  • メニュー内がスクロールできない(高さとoverflow)
  • スマホで横スクロールが出る(right:-100% / 100vwの罠)

私も昔、right: -100% で隠したつもりが、スマホだけ横スクロールが出て焦りました。
原因はメニューの幅と位置指定の組み合わせで、画面外に“実体”が残っていたこと。
見た目は隠れてても、レイアウト的にははみ出してる…ってやつです。

この記事では「スライドメニュー css」で検索してきた人が、
実装 → よくある事故回避 → デバッグまで一気に進められるようにまとめます。


スライドメニューとは

スライドメニューは、画面の外から横方向にスライドして表示されるナビゲーションのことです。

よくあるパターンはこの3つ。

  • 右からスライド
  • 左からスライド
  • 画面全体を覆う(フルスクリーン)

スマホでは特に、メニューを常に表示しなくて済むので、見た目も操作も整えやすいです。


CSSだけでスライドメニューは作れる?

結論、作れます。
ポイントはこれだけ。

  • チェックボックスで「開いてる/閉じてる」を持つ
  • 画面外に置いておいて、開いたら戻す
  • transitionで滑らかに動かす

ただし、実務で使うなら「背景クリックで閉じる」「スクロール」「横スクロール対策」「フォーカス」も入れておくと安心です。


最小構成のHTML(まず動かす)

まずは構造を固定します。これがズレるとCSSが効きません。

<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="slide-menu" aria-label="グローバルナビゲーション">
  <ul class="slide-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(最低限)

.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;
}

右からスライドするメニュー(基本形)

.slide-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 ~ .slide-menu {
  transform: translateX(0);
}

ここが実務的に効くポイント

  • right: -100% ではなく、transformで隠す
    → はみ出しが原因の横スクロール問題を起こしにくい
  • height: 100svh
    → スマホのアドレスバーで高さが変わる問題を減らせる
  • overflow-y: auto
    → メニュー項目が多くてもスクロールできる

背景(オーバーレイ)を出して、タップで閉じる

「背景が操作できてしまう」問題は、これでほぼ解決します。

.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方向を変えるだけ。

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

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

レスポンシブ対応(PCでは通常メニューにする)

「スマホだけスライド・PCは普通のナビ」が定番です。

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

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

よくあるトラブルと対処(リアルにハマるやつ)

メニューが表示されない

だいたい原因は2つです。

  • HTMLの並び順が違う
  • CSSのセレクタが合ってない

今回の例は ~(一般兄弟セレクタ)を使っています。
checkboxより後ろに .slide-menu が存在していないと効きません。

DevToolsでの確認手順

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

「チェックは付くけどCSSが動かない」なら、HTMLの順番かセレクタです。


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

高さが固定されていなかったり、overflowが無いと起きます。

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

背景が操作できてしまう(押せる・スクロールする)

  • overlayを入れる
  • z-indexをメニューより1つ下にする

この記事の構成なら、overlayが先に出て背景をブロックします。


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

原因として多いのはこのあたり。

  • right: -100% + width: 80% などで画面外に実体が残る
  • 100vw を多用して微妙にオーバー
  • メニュー内の長い文字(英数字)が折り返されない

対策の基本

  • transformで隠す(今回の方式)
  • 長い文字は折り返す
.slide-menu a {
  overflow-wrap: anywhere;
}

CSSだけのスライドメニューのメリット・デメリット

メリット

  • JavaScriptなしで軽い
  • 実装がシンプル
  • LPや小規模サイトなら十分使える

デメリット

  • フォーカス制御(キーボード操作)などは限界がある
  • 開閉状態に合わせて aria-expanded を切り替える…みたいな細かい制御は苦手

「とりあえず動く」ならCSSのみでOK。
アクセシビリティを徹底するなら、最終的にJavaScript併用も検討する、でバランスが取れます。


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

最後に、動く形をまとめて置きます。

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

.slide-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 ~ .slide-menu {
  transform: translateX(0);
}

.slide-menu a {
  overflow-wrap: anywhere;
}

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

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

まとめ|CSSだけでも“実務で使える”スライドメニューは作れる

CSSだけのスライドメニューは、仕組みさえ押さえれば十分実用です。

  • checkboxで開閉状態を持つ
  • transform + transition でスライド演出
  • overlayで背景タップ閉じ・誤操作防止
  • overflowでメニュー内スクロール
  • 横スクロール問題はtransform方式で回避しやすい
  • DevToolsでcheckedと打ち消し線を見れば原因が特定できる

「スライドメニュー css」で探しているなら、
まずはこの記事の基本形をコピペして動かしてみてください。
動いたら、右/左、幅、デザインを自分のサイトに合わせて整えるだけです。

タグ:

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