iPhoneでモーダルの背景のスクロールを止める
以前の記事「モーダルの背景のスクロールを止める」
上の記事で、メニューなどをモーダルで出す場合に背景のスクロールを止める方法を書いたのですが、やはり、iPhone 実機ではうまくいきません。再度挑戦です。
01iPhone(iOS?)以外の場合
iPhone 以外は上の記事で問題ないと思います。モーダルを開いた時に body
に open
などのクラスを追加します。たとえば、
document.getElementById('トリガー要素のid').addEventListener('click', function(){ document.body.classList.toggle('open') });
として、CSS で
body.open { overflow: hidden; }
とすれば止まります。
今回の件でいろいろググってみたところ、height: 100%;
や html { overflow: hidden;}
が必要との記事が多かったのですが、私の環境では必要ありませんでした。いろいろ試してみるのが一番ですね。
02iPhone の場合
iPhone しか持っていませんので、iOS 共通のことがどうかわかりません。おそらくそうだとは思いますが、iPhone 上の Safari と Chrome でのチェックのみです。
「モーダルの背景のスクロールを止める(iPhoneの場合)」
上の以前の記事の方法では問題が発生します。モーダルを表示しない通常のコンテンツでのスクロールがうまくいきません。一応スクロールはするのですが、いわゆるヌルヌル感がなくなります。
で、いろいろググりましたら、 preventDefault()
を使うという記事があり、なるほどということでやってみたのですが、当然ながら、これを使いますとモーダルのスクロールまで止まってしまいます。
こういう方法を考えてみました。
結局、背景がスクロールしてしまうのは、モーダルがもうこれ以上スクロールできない状態の時に背景がスクロールするわけですから、モーダルが一番上や一番下までスクロールしたら、もうそれ以上スクロールしないようにすればいいわけです。ですので、モーダルが一番下までスクロールされたら、preventDefault()
でイベントをキャンセルし、そのままではキャンセルされたままになってしまいますので 1px
だけスクロールさせキャンセルを解除します。一番上までスクロールしたときも同様にします。
モーダル表示のトリガーが関数 togglemodal()
を呼ぶとして、
function togglemodal() { if(!document.body.classList.contains('open')){ document.body.classList.add('open'); var elem = document.getElementById('モーダルのid'); elem.addEventListener('touchmove', function(e) { var scroll = elem.scrollTop; var range = elem.scrollHeight - elem.offsetHeight - 1; if (scroll < 1) { e.preventDefault(); elem.scrollTop = 1; } else if(scroll > range) { e.preventDefault(); elem.scrollTop = range; } }); } else { document.body.classList.remove('open'); } }
(2019.4.17)以下のように IPhone で切り分けないと Android ではスクロールしなくなるようです。
if(navigator.userAgent.indexOf('iPhone') !== -1){ } // または if(navigator.userAgent.indexOf('iPhone') !== -1 || navigator.userAgent.indexOf('iPad') !== -1){ }
これで、iPhone 実機でもうまくいっています。