JavaScript

【サンプルあり】ネイティブJSとCSSでメニューを開いている間は背景スクロールを禁止にする

今回はJavaScript(Vanilla JS)とちょっとのCSSを使って、メニューを開いている間は背景スクロールを禁止にする実装方法を紹介します。

サンプル

See the Pen Restrict scrolling while we open menu by POSIPAN (@posipan) on CodePen.

仕様

  1. メニューボタンをクリックした時に、メニューが表示される。
  2. 同時に、html要素にスクロールを禁止にするためのクラスを追加する。
  3. メニューを閉じた時、スクロール禁止を解除する。(クラスの削除)

コード解説

SCSS

CodePenには色々書いていますが、ポイントとなる記述は下記です。

メニューボタンをクリックした時に、html要素に.fixedを追加します。
overflow: hidden;により、スクロールができなくなるようにしています。

html {
  &.fixed {
    height: 100%;
    overflow: hidden;
  }
}

【2022.05.31追記】JavaScriptのコードを簡略化したため、.navのSCSSを変更しました。

JavaScriptでフェイドアニメーションさせていましたが、今回の変更ではCSSのtransitionでアニメーションさせています。

ここで大事なのはpointer-eventsプロパティです。

opacity: 0;は透明度の影響で要素は見えなくなりますが、display: none;非表示になるわけではありません。

ゆえにリンクがあればクリックできてしまうので、これをpointer-events: none;よってクリックを無効にし、非表示を擬似的に表現しています。

.nav {
  opacity: 0;
  pointer-events: none; // クリックを無効にする
  transition: 0.3s ease transform, 0.3s ease opacity;
  background: rgba(0, 0, 0, 0.5);
  position: fixed;
  top: 0;
  left: 0;
  z-index: 99;
  width: 100%;
  height: 100%;
  
  &.active {
    opacity: 1;
    pointer-events: auto; // クリックを有効にする
  }
}

JavaScript

基本的には、.menu-btnをクリックした際に
クラスの追加・削除の切り替えを行なっているだけです。

コード内のthismenuBtnを指しています。

詳細はコード内のコメントに記載しています。

// 要素の取得
const html = document.documentElement;
const menuBtn = document.querySelector('.menu-btn');
const nav = document.querySelector('.nav');

// .menu-btnをクリックした時、
menuBtn.addEventListener('click', function() {
  // .menu-btnに.activeがなかったら、
  // .activeを追加し、html要素に.fixed、.navに.activeを追加する。
  if (!this.classList.contains('active')) {
    this.classList.add('active');
    html.classList.add('fixed');
    nav.classList.add('active');
  } else {
    // .menu-btnに.activeがすでに追加されていれば、
    // .activeを削除し、html要素の.fixed、.navの.activeを削除する。
    this.classList.remove('active');
    html.classList.remove('fixed');
    nav.classList.remove('active');
  }
});

完成です!