##現象
モーダル表示される時に普段はoverflow hiddenして、スクロールさせない様にしてますが、iOSはoverflow hiddenしてもスクロールされるためbodyにfixedし、ずれた分のScrollTopからの位置をあてて対応してました。
ところがiOS15にてその対応を行っているページで不具合が発生しました。
どうやらbodyにfixedすることでiOSで新たに追加された機能(タブバー)のせいなのかわかりませんが、bottomの基準位置が見た目とズレちゃうみたいなんですよね。
これがどういう状況で起こるかというと、下記に該当している場合です。
1.ページ下部にナビゲーションをfixedで置いている。(bottom: 0;など。)
2.modalなどの処理でbodyまたはhtmlにfixedしている時。
modalを開いてbody fixedしてスクロールを固定させると既に置いているページ下部のナビゲーションがタブバーの高さ分?隙間が出ちゃいます。
##対処法
とりあえずコードを。
class Ios15ModalHack {
constructor() {
this.init();
this.load();
this.resize();
}
init() {
const styleTag = document.createElement('style');
styleTag.innerText = "html.is-locked,html.is-locked body {height: calc(var(--window-inner-height) - 1px);overflow: hidden;box-sizing: border-box;}"
document.getElementsByTagName('head')[0].insertAdjacentElement('beforeend', styleTag);
}
syncHeight() {
document.documentElement.style.setProperty (
"--window-inner-height",
`${window.innerHeight}px`
);
}
load() {
window.addEventListener('load', () => {
this.syncHeight();
});
}
resize() {
window.addEventListener('resize', () => {
this.syncHeight();
})
}
}
const App = new Ios15ModalHack();
headに必要なstyleをjs側で挿入して、
モーダル発火時にそのクラス( html.is-locked )をつけることで謎の隙間を防止します。
fixedは使いません。
内容としてはモーダル展開時にスクロール量が内部的にあると起こる?らしいので
発火時にはwindow.innerHeightでhtmlのheightを固定してしまおうという内容です。
CSS側で
height: calc(var(--window-inner-height) - 1px);
と謎の1pxを引いてますが、これが無いと展開時に垂直スクロールでタブバーの誤動作が起きて不具合が起きるそうです。
iOS15は他にも不具合ありそうなので注意が必要ですね...。
下記参考させていただきました。
https://pqina.nl/blog/how-to-prevent-scrolling-the-page-on-ios-safari/