JavaScript:背景スクロールを固定する、おすすめライブラリ

モーダル画面表示時や、スマホのハンバーガーメニューを開いた時に、背景スクロールを固定するライブラリを紹介します。

実現したかったこと。

  • 任意のタイミングで、背景となるbody部分のスクロールを固定する
  • IOS safari でも動作する
  • 開いている前面のメニュー部分はスクロール可能にする

シンプルそうに見えてなかなか難しいです。
だいぶ苦戦しましたが、こちらのライブラリで実装できました。

https://github.com/willmcpo/body-scroll-lock

使い方

スマホのハンバーガーメニューを例に実装します。

HTML

ちょっと冗長になってますが…<nav> 部分がメニューです。
jsで要素を取得しやすいように、任意のIDを設定(今回は id=”nav”

<div class="wrapper">
      <nav id="nav"> // メニュー部分。IDを設定
        <ul>
          <li><a href="">めにゅー1</a></li>
          <li><a href="">めにゅー2</a></li>
          <li><a href="">めにゅー3</a></li>
          <li><a href="">めにゅー4</a></li>
          <li><a href="">めにゅー5</a></li>
          <li><a href="">めにゅー6</a></li>
          <li><a href="">めにゅー7</a></li>
          <li><a href="">めにゅー8</a></li>
          <li><a href="">めにゅー9</a></li>
          <li><a href="">めにゅー0</a></li>
        </ul>
      </nav>
      <div class="content">
        <p class="click" id ="click"><span>click!!</span></p>
        <p>some contents</p>
        <p>some contents1</p>
        <p>some contents2</p>
        <p>some contents3</p>
        <p>some contents4</p>
        <p>some contents5</p>
        <p>some contents6</p>
        <p>some contents7</p>
        <p>some contents8</p>
        <p>some contents9</p>
      </div>
    </div>

表示は以下の動画の通り。
スタイルは割愛していますが、メニュー部分にposition: absolute; をかけ、
ボタン要素がクリックされた時に、rightの位置を戻しています。
まだ、後ろの背景はスクロールされる状態です。

メニュー要素に設定したIDで要素を取得し、bodyScrollLock に設定します。

function用途
bodyScrollLock.disableBodyScroll( ‘hoge’ )‘hoge’ 以外のスクロールを禁止
bodyScrollLock.clearAllBodyScrollLocks( )全てのスクロール禁止を解除

javascript

スクロールを禁止したくない要素を設定してあげます。
最初、スクロール禁止をかけたい部分(bodyとか)を設定するのかと思ってました…

const btn = document.getElementById('click');
const nav = document.getElementById('nav');

btn.addEventListener('click' , () => {
  if(nav.classList.contains('open')){
    nav.classList.remove('open');
        // 固定解除
    bodyScrollLock.clearAllBodyScrollLocks();
  } else {
    nav.classList.add('open');
        // 背景固定
    bodyScrollLock.disableBodyScroll(nav);
  }
});

上の書き方はjavascript用ですが、npm でインストールして設定する場合など
使用状況のパターンでいろいろと記述が変わってきます。

ページトップのリンクからライブラリのgitに飛べますので
ReadMeを参考にしてみてください。🙇


実装結果です。
背景は固定されていますが、前面のメニューはスクロールできます。
なかなか動画では伝わりづらいな..と思うのでぜひ実装して試してみて欲しいです。

そのうちデモぺーじもつくろうかと。多分。

上手くいかなかった試み

このライブラリを見つけるまでの戦いの記録…
もっと早く知りたかったほんとに…

Bodyにoverflow:hidden;

最も一般的な方法だと思います。iOS safari に効きません。
そこまでこだわりないのであれば、これで良いのではと思ったりします。

Scrollevent の禁止

javascriptを使ってスクロールイベントを禁止します。
safari にも有効ですが、モーダルコンテンツやメニューが長かった場合、
その部分までスクロールすることができなくなります。
スマホ横にされると短いコンテンツでもスクロールできなくなるので辛いですね…

Position fixed

こちらは、スクロール位置の情報が失われてページの1番上に戻ってしまいます。top: 〇〇pxなどで調整しても、一瞬画面にチラつきが発生します。

ライブラリ開発者の方に、感謝です。

こっちも読んでみる?

おすすめ記事

記事一覧へ