✅ 【JavaScript】ハンバーガーメニューを開いたときに背景をスクロールさせない方法
スマホサイトでよく見かけるハンバーガーメニュー。 メニューを開いたとき、背景(ページ全体)がスクロールできてしまうのはUX的に問題があります。
今回は、jQuery を使ってハンバーガーメニューを開いたときに背景を固定(スクロールできないように)する方法を、初心者向けにわかりやすく解説します。
🧩 なぜ背景がスクロールするのを防ぐ必要があるの?
ハンバーガーメニューを開いた状態で背景がスクロールできると、以下のような問題が発生します:
- 誤タップの原因に: ユーザーが意図せず背景のリンクをタップしてしまう
- 視覚的な違和感: メニューを見ているのに背景が動くと混乱する
- 操作性の低下: どちらを操作しているのか分かりにくくなる
背景を固定することで、ユーザーはメニューの操作に集中でき、より快適なユーザー体験を提供できます。
✅ 実装方法(jQuery)
① HTML構造の例
BEM記法を使用した、セマンティックで保守性の高いHTML構造です。
<!-- ハンバーガーボタン -->
<button
class="header__nav-toggle"
type="button"
aria-expanded="false"
aria-controls="header-nav"
aria-label="メニューを開く"
>
<span class="header__nav-toggle-line"></span>
<span class="header__nav-toggle-line"></span>
<span class="header__nav-toggle-line"></span>
</button>
<!-- メニュー本体 -->
<nav class="header__nav" id="header-nav" aria-label="グローバルナビゲーション">
<ul class="header__nav-list">
<li class="header__nav-item">
<a href="#" class="header__nav-link">ホーム</a>
</li>
<li class="header__nav-item">
<a href="#" class="header__nav-link">サービス</a>
</li>
<li class="header__nav-item">
<a href="#" class="header__nav-link">お問い合わせ</a>
</li>
</ul>
</nav>
ポイント:
aria-expanded: メニューの開閉状態をスクリーンリーダーに伝えるaria-controls: ボタンが制御する要素を明示aria-label: ボタンの用途を明確に説明
② CSSで基本スタイル
/* 背景スクロール防止用 */
body.no-scroll {
overflow: hidden;
}
/* ハンバーガーメニュー */
.header__nav {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: #fff;
z-index: 1000;
}
.header__nav.is-active {
display: block;
}
CSS のポイント:
position: fixed: メニューを画面に固定z-index: 1000: メニューを最前面に表示.is-active: 状態を表すクラスで開閉を制御
③ jQueryでメニュー開閉+背景固定
// ハンバーガーメニュー
$(document).ready(function() {
const $navToggle = $('.header__nav-toggle');
const $headerNav = $('.header__nav');
const $navLinks = $('.header__nav-link');
let scrollPosition = 0;
// メニューボタンクリックイベント
$navToggle.on('click', function() {
const isActive = $(this).hasClass('is-active');
if (!isActive) {
scrollPosition = $(window).scrollTop();
$(this).addClass('is-active');
$headerNav.addClass('is-active');
$('body').css({
'position': 'fixed',
'width': '100%',
'top': -scrollPosition + 'px'
});
$(this).attr({
'aria-label': 'メニューを閉じる',
'aria-expanded': 'true'
});
} else {
$(this).removeClass('is-active');
$headerNav.removeClass('is-active');
$('body').css({
'position': '',
'width': '',
'top': ''
});
document.documentElement.style.scrollBehavior = 'auto';
$(window).scrollTop(scrollPosition);
requestAnimationFrame(function() {
document.documentElement.style.scrollBehavior = 'smooth';
});
$(this).attr({
'aria-label': 'メニューを開く',
'aria-expanded': 'false'
});
}
});
// ナビゲーションリンククリックイベント
$navLinks.on('click', function(e) {
e.preventDefault();
const href = $(this).attr("href");
const $targetElement = $(href);
$navToggle.removeClass('is-active');
$headerNav.removeClass('is-active');
$('body').css({
'position': '',
'width': '',
'top': ''
});
document.documentElement.style.scrollBehavior = 'auto';
$(window).scrollTop(scrollPosition);
$navToggle.attr({
'aria-label': 'メニューを開く',
'aria-expanded': 'false'
});
if ($targetElement.length) {
setTimeout(function() {
document.documentElement.style.scrollBehavior = 'smooth';
window.location.hash = href;
}, 50);
} else {
requestAnimationFrame(function() {
document.documentElement.style.scrollBehavior = 'smooth';
});
}
});
// ESCキーでメニューを閉じる
$(document).on('keydown', function(e) {
if (e.key === 'Escape' && $navToggle.hasClass('is-active')) {
$navToggle.trigger('click');
}
});
});
🔍 実装のポイント解説
背景スクロール防止の仕組み
1.スクロール位置を保存
scrollPosition = $(window).scrollTop();
メニューを開く前のスクロール位置を変数に保存します。
2.body を固定
$('body').css({
'position': 'fixed',
'width': '100%',
'top': -scrollPosition + 'px'
});
position: fixed: body を固定してスクロールを防止width: 100%: iOS で表示崩れを防ぐtop: -scrollPosition + 'px': 表示位置がずれないように調整
3.元の位置に復元
$('body').css({
'position': '',
'width': '',
'top': ''
});
$(window).scrollTop(scrollPosition);
メニューを閉じたら、保存しておいたスクロール位置に戻します。
🎯 デモ
実際の動作を確認できるCodePenのデモを用意しました。
https://codepen.io/npupiwfh-the-sans/pen/JoKajPo
ハンバーガーメニューを開いた状態でスクロールを試すと、背景が固定されていることが確認できます。
⚠️ よくあるミスと解決策
| ミス内容 | 原因 | 解決策 |
|---|---|---|
| メニューを閉じるとページ上部に戻る | スクロール位置の保存・復元を忘れている | scrollPosition 変数でスクロール位置を保存し、scrollTop() で復元する |
| iOS で表示がずれる | body の幅が指定されていない | width: 100% を必ず設定する |
| メニューを開いた位置がずれる | top プロパティの設定を忘れている | top: -scrollPosition + 'px' で現在位置を保持する |
💡 さらなる改善案
ESC キーでメニューを閉じる
アクセシビリティを向上させるため、ESC キーでメニューを閉じられるようにします。
// ESCキーでメニューを閉じる
$(document).on('keydown', function(e) {
if (e.key === 'Escape' && $navToggle.hasClass('is-active')) {
$navToggle.trigger('click');
}
});
スムーズスクロールとの連携
アンカーリンクをクリックした際、メニューを閉じてからスムーズにスクロールさせることもできます。
✅ まとめ
ハンバーガーメニューを開いたときに背景が動いてしまうのは、ユーザー体験を損なう原因になります。
今回紹介した方法を使えば、わずかなコードで快適なメニュー操作を実現できます。ぜひあなたのサイトにも取り入れてみてください!
実装のポイント:
- ARIA 属性でアクセシビリティにも配慮
- スクロール位置の保存と復元が重要
position: fixedとtopの組み合わせで表示位置を維持
✉️ あなたのリクエスト教えてください!
「この記事わかりやすかった!」
「他にもこんな記事書いてほしい!」
そんな声を、ぜひXのDMで教えてください!😊📩
できるだけリクエストにお応えして、今後の記事作成に活かしていきます!
▶️ Xもフォローしてもらえるとめちゃくちゃ嬉しいです!
コメントを残す