SPメニュー表示時に背景をスクロールさせない

この記事を読むのにかかる時間 1未満

概要

SPメニューを表示した時、スクロールすると後ろの背景ページもスクロールできてしまう問題がある。
一般的に、overflow:hiddenをbodyに当てることで対策するが、1点問題がある。SPメニューを表示したときに、背景ページが一番上までスクロールしてしまう不具合が生じてしまう場合がある。


そのため、本実装をする際は、以下を満足する処理を実装する必要がある。
・背景ページはスクロールできないようにする
・背景ページのスクロール位置はそのままにする

コード

以下コードは既存の処理も含んでいるため一般化はできていないため、太文字部のみ参照のこと。

  var $sp_menu = $('.spMenuBtn').closest('.sp_menu');
  var scrollPosition = 0;

  function noScroll(e) {    //eは動作の情報
    e.preventDefault();    //「スクロールしていいよ」というブラウザの標準動作を止める命令
    window.scrollTo(0, scrollPosition);  //元の位置に強制的に戻す。scrollTo(横位置,縦位置)
  }

  function preventTouch(e) {
    if (!$(e.target).closest('#gMenu').length) { //タッチ動作がgMenuの中かどうかを判定
      e.preventDefault();  //タッチ動作がgMenuの外(背景部)ならスクロールさせない
    }
  }

$('body').on('click', '.spMenuBtn', function () {

  if ($sp_menu.hasClass('active')) {
    document.removeEventListener('wheel', noScroll, { passive: false });    //マウススクロールなどが対象、jsでスクロールを止める
    document.removeEventListener('touchmove', preventTouch, { passive: false });    //iphoneの場合に有効、jsでスクロールを止める
  }
});

e.preventDefault()とは

eはどんなイベントがどこで起きたかなどのイベントの内容を指す。preventDefaultをつけることで、この標準動作が発生することを防いでいる(preventは「防ぐ」という意味)。

{ passive: false }とは

passiveは何もしないという意味。
{ passive: true }・・・ 正常な状態。js処理は何もしないよ、という状態。
          スクロールを止めるjsを書いても、無視されてしまう。

{ passive: false }・・・js処理のために処理を待つよ、という状態。
          スクロールを止めるjsの場合、そちらが優先される。
          そのため、スクロール処理では必須になる。