モバイルファーストの時代では、スマートフォン向けのメニューの使いやすさが、ユーザー体験(UX)の向上に大きく貢献します。この記事では、スマートフォンメニューを作成する際に必要な、スクロール禁止とアンカーリンクでメニューが閉じる機能の実装方法を、初心者でもわかりやすく解説します。
モバイルメニューの基本構造
まず、シンプルなモバイルメニューをHTMLで作成します。メニューを開くボタンとメニュー内容を含め、リンクで指定した場所にスクロールする基本的な構造です。
<!-- メニューを開くボタン -->
<button class="menu-button">メニューを開く</button>
<!-- メニュー本体 -->
<div class="menu">
  <button class="close-button">× 閉じる</button>
  <nav>
    <ul>
      <li><a href="#contentA" class="menu-link">コンテンツA</a></li>
      <li><a href="#contentB" class="menu-link">コンテンツB</a></li>
      <li><a href="#contentC" class="menu-link">コンテンツC</a></li>
      <li><a href="#contentD" class="menu-link">コンテンツD</a></li>
    </ul>
  </nav>
</div>CSSでメニューのデザイン
次に、メニューを画面全体に表示させるためのCSSを追加します。モバイル画面にぴったりのデザインを適用します。
body {
  font-family: Arial, sans-serif;
}
.menu-button {
  position: fixed;
  top: 20px;
  left: 20px;
  padding: 10px 20px;
  background: #333;
  color: #fff;
  border: none;
  cursor: pointer;
}
.menu {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  transform: translateY(-100%);
  transition: transform 0.3s ease-in-out;
}
.menu.open {
  transform: translateY(0);
}
.close-button {
  background: red;
  color: white;
  border: none;
  padding: 10px;
  margin-bottom: 20px;
  cursor: pointer;
}
.menu nav ul {
  list-style: none;
  padding: 0;
  text-align: center;
}
.menu nav ul li {
  margin: 15px 0;
}
.menu nav ul li a {
  color: white;
  text-decoration: none;
  font-size: 1.5rem;
}JavaScriptでスクロール禁止とメニューの開閉を制御
ここでは、メニューを開いた時にスクロールを完全に停止し、メニュー内のリンクをクリックするとメニューが閉じるようにします。これを実現するためには、JavaScriptでスクロール禁止とイベント制御を行います。
const menu = document.querySelector('.menu');
const menuButton = document.querySelector('.menu-button');
const closeButton = document.querySelector('.close-button');
const menuLinks = document.querySelectorAll('.menu-link');
let scrollPosition = 0; // スクロール位置を保存する変数
function disableScroll() {
  scrollPosition = window.scrollY; // 現在のスクロール位置を保存
  document.body.style.overflow = 'hidden';
  document.body.style.position = 'fixed';
  document.body.style.width = '100%';
  document.body.style.height = '100%';
  document.body.style.top = `-${scrollPosition}px`;
  document.addEventListener('touchmove', preventDefault, { passive: false });
  document.addEventListener('wheel', preventDefault, { passive: false });
}
function enableScroll() {
  document.body.style.removeProperty('overflow');
  document.body.style.removeProperty('position');
  document.body.style.removeProperty('width');
  document.body.style.removeProperty('height');
  document.body.style.removeProperty('top');
  window.scrollTo(0, scrollPosition); // 保存したスクロール位置に戻す
  document.removeEventListener('touchmove', preventDefault);
  document.removeEventListener('wheel', preventDefault);
}
function preventDefault(event) {
  event.preventDefault();
}
menuButton.addEventListener('click', () => {
  menu.classList.add('open');
  disableScroll();
});
closeButton.addEventListener('click', () => {
  menu.classList.remove('open');
  enableScroll();
});
// メニュー内のリンクをクリックしたら閉じる
menuLinks.forEach(link => {
  link.addEventListener('click', (event) => {
    menu.classList.remove('open');
    enableScroll();
  });
});動作の仕組み
現在のスクロール位置を保存
メニューが開かれるとき、現在のスクロール位置を保存します。これにより、メニューを閉じた後、スクロール位置が元の位置に戻ります。
scrollPosition = window.scrollY;position: fixed;を適用してスクロールを完全に停止
メニューが開くと、document.body.style.position = 'fixed';により、ページ全体が固定され、スクロールを防ぎます。
スクロール関連のイベントをpreventDefault()で阻止touchmoveやwheelなどのスクロールイベントをpreventDefault()で阻止し、ユーザーがスクロールできないようにします。
メニューを閉じたらスクロール位置を元に戻す
メニューを閉じる際に、window.scrollTo()で保存したスクロール位置にページを戻します。
iOS特有のバグとその回避方法
iOSでは、position: fixedを使った際にスクロールが正しく機能せず、画面がずれる問題が発生することがあります。そこで、今回は以下の方法でiOS特有のバグを回避しています。
どちらを使うべきか?
この方法を使うことで、iOSでもバグを回避し、Androidでも確実に動作します。スクロール位置を記憶することで、メニューを閉じても元のスクロール位置に戻り、スムーズなユーザー体験が提供できます。
サンプル
See the Pen Side-menu-button by kasasagi_kmnmc (@kasasagi_kmnmc) on CodePen.
まとめ
この記事では、モバイルメニューの作成方法と、スクロール禁止およびアンカーリンクでメニューが閉じる機能の実装方法を解説しました。iOSでもバグを回避したスクロール制御を取り入れることで、どのデバイスでも安定して動作します。
初心者の方でも理解しやすいように、実装方法とそのメリットについても説明しました。ぜひ、この記事を参考にして、自分のWebサイトでスマートフォン向けの快適なメニューを作成してみてください。

 
  
  
  
   
    
