事象
コンテンツが多い一覧ページをスマホのブラウザで開くと、
https//hogehoge.comで問題が繰り返し起きました。
問題が起きたため、このWebページを再度読み込みました
といった現象に遭遇した。
【環境】
検証端末:iphone XS、iphone12Pro
iOS:15.4.1
Safari:15.4
Chrome:100.0.4896.85
詳細
調査の過程で以下のようなことがわかりました。
・PCブラウザでは発生しない(chrome、Safari、firefox)
・iOSのSafariだけでなく、iOS版のchromeでも似た現象になる
・キャッシュやcookieなどを削除しても現象は起こる
・webフォントやJSなどは使っていない
・ページ内のコンテンツ数を減らすと表示できる
・コンテンツ数を減らした状態でページにアクセスし、ページ内をスクロールすると一瞬白くなるが、少し経つと描画されるいった現象が起きる
原因
私が遭遇した事例の場合では、
CSSのfilter: drop-shadow()
が原因を引き起こしていました。
■該当ソース
<div class="container">
<div class="grid-item">コンテンツ1</div>
<div class="grid-item">コンテンツ2</div>
<!--中略-->
<div class="grid-item">コンテンツ60</div>
</div>
.grid-item{
filter: drop-shadow(0px 0px 5px #ccc);
}
解説
3D Transform やcss filterなどのCSSアニメーションに関するプロパティは、指定がない場合CPUのみで処理しようとするため、表示の乱れやレンダリング速度の低下、ブラウザが固まるなどの現象が起きてしまうようです。
私が体験した事例はコンテンツが多すぎることが主な原因ですが、
根本はCSSアニメーションはリペイントを繰り返すため、端末のCPUが描画処理に耐えきれずに上記のような現象を引き起こしたというのが私の見解です。
対策
GPU側に処理を助けて貰えるようにGPUレイヤーを作成するようにします。
対応方法①
translateZ(0)
をつける。
昔からある手法で、GPUによるレンダリング処理を高速化するような場合に使われています。
.grid-item{
filter: drop-shadow(0px 0px 5px #ccc);
translateZ(0);
}
対応方法②
will-change: filter
をつける。
こちらもGPUレイヤーを作ることができます。
元々の用途はブラウザにレンダリングを予告し、これから起きる変化に備えて最適化を行わせるためのようです。
.grid-item{
filter: drop-shadow(0px 0px 5px #ccc);
will-change: filter;
}
注意
上記のどちらを使う場合でも大量にリソースを消費します。
そのため不要に要素全体に当てるのではなく、必要な箇所にだけ当てるのが望ましいです。
どうしても一覧で出す理由がない場合はページネーションなどでページを分ける事も検討すべき。
参考記事
当問題の解決にあたり、下記を参考にさせていただきました。
■解決のヒント
iOS SafariはCSSのfilterプロパティを使用すると重くなる
iOS Safariでcss filterを掛けると表示が壊れるときの対処法
■仕組みを知る
CSS アニメーションについて深く知る
CSS will-changeプロパティについて知っておくべきこと
■検証方法
GPUで処理されているかどうか
以上となります。
参考になれば幸いです。