🔒
body-scroll-lockというライブラリを使ってドロワーメニュー、モーダルの背景スクロールを固定する
ScrollTriggerを使っていたら意図しない挙動になった
これまで背景スクロール固定はZennで紹介されていたこちらの方法を導入していました。GSAPとScrollTriggerを使って、pinを使ったスクロールジャックがあるアニメーションを実装していたのですが、ドロワーメニューを開く瞬間にスクロールジャックした要素が謎の挙動で出現しまう現象にぶつかりました。
しかし某案件で救世主「body-scroll-lock」
色々検索していたところ「body-scroll-lock」(以後BSL)というライブラリに出会ったので導入してみたところ、上記の現象が起こらずに無事実装できました。
BSLの特徴
公式のGitHubのFeaturesでは次のように書かれています。
- disables body scroll WITHOUT disabling scroll of a target element
- works on iOS mobile/tablet (!!)
- works on Android
- works on Safari desktop
- works on Chrome/Firefox
- works with vanilla JS and frameworks such as React / Angular / VueJS
- supports nested target elements (eg. a modal that appears on top of a flyout)
- can reserve scrollbar width
-webkit-overflow-scrolling: touch
still works
そうなんです、スクロール関係で悪さを起こしがちなiOS Safariにも対応しているのです!素晴らしい👏
またドキュメントにはVanilla.jsだけでなく流行りのReactでの導入の仕方も書かれているので、様々な場面で導入できそうです。
デモ
使い方
特に難しいことはなく、ライブラリを読み込んで実行するだけです。
main.js
const disableBodyScroll = bodyScrollLock.disableBodyScroll;
const enableBodyScroll = bodyScrollLock.enableBodyScroll;
// この要素以外のスクロールをロックする(ここにドロワーメニューやモーダルを指定する)
const targetElement = document.querySelector('#someElementId');
// スクロールをロックする
disableBodyScroll(targetElement);
// ロックを解除する
enableBodyScroll(targetElement);
オプション
オプションにはスクロールロックで必要になりがちなスクロールバー分の余白の追加もできます。(body
にpadding-right
を追加)
main.js
const disableBodyScroll = bodyScrollLock.disableBodyScroll;
const enableBodyScroll = bodyScrollLock.enableBodyScroll;
// オプション
const options = {
reserveScrollBarGap: true, // bodyにスクロールバー分のpadding-rightを追加するかどうか(デフォルト値:false)
};
// この要素以外のスクロールをロックする(ここにドロワーメニューやモーダルを指定する)
const targetElement = document.querySelector('#someElementId');
// スクロールをロックする(オプション追加)
disableBodyScroll(targetElement,options);
// ロックを解除する
enableBodyScroll(targetElement);//解除するときはoptionsつけなくても大丈夫です。多分。
あとallowTouchMove
というオプションもあるみたいです。
気になる方はGitHubをご確認ください。
参考サイト
Discussion