モーダルを作る際に面倒なのが、スクロールしたときの背景の固定。
別に背景が動いても直接問題が起きることはないのですが、やっぱり気にはなります。ユーザーにもこのサービス大丈夫かな...と余計な不安感を与えることにもなりますし。
ただ、この背景固定、一筋縄ではいかないのが面倒なところ。とくにiOSは他のデバイスと異なる挙動を示し、AndroidやWebではちゃんと固定されるのにiOSだけ上手くいかない...と悩んでいる人も多いと思います。
何か解決方法はないかと探していたところ、非常に便利なライブラリを見つけたので、それで対応することにしました。
Body Scroll Lockを使う
名前の通り、機能を有効にすることで背景のスクロールを無効にできるライブラリです。便利なのは、ページ全てをスクロール無効にするのではなく、指定したDOM内部だけはスクロールできるように設定できること。
モーダル内部はスクロールさせたい!なんてケースにも対応可能ということです。
githubでのスターも1400個以上ついていますし、ある程度安心して導入できるのもメリットですね。公式サイトはこちら↓
Body Scroll Lockの使い方
何はともあれ、まずはnpm/yarnでinstallしましょう。
npm install body-scroll-lock
次に、背景固定を行いたいページ(コンポーネント)でimportします。
import { disableBodyScroll, enableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
名前からしてそのままですが、背景を固定したい場合はdisableBodyScrollを、解除したい場合はenableBodyScrollを使えばOKです。
たとえば、モーダルコンポーネントに使うならこんな感じ。
<template>
<div class="modal-layer">
<div class="modal">
<slot />
</div>
</div>
</template>
<script>
import {
disableBodyScroll,
enableBodyScroll,
clearAllBodyScrollLocks
} from 'body-scroll-lock';
export default {
mounted() {
const modal = document.querySelector('.modal')
disableBodyScroll(modal)
},
beforeDestory() {
clearAllBodyScrollLocks()
}
}
</script>
ModalLayoutは親コンポーネントからv-ifで呼ばれる想定のコンポーネントです。
v-ifがtrueになったときにmounted()が走ることと、falseになるとbeforeDestoryが走ることを利用して、モーダルが表示されている場合にのみ背景が固定されるようにしています。
まとめ
非常にシンプルで使いやすいので、背景固定に困っているケースで便利です。モーダル系ライブラリとも簡単に組み合わせられそうなのも良さそうですね。