css filter はぼかしや色変化など、要素に様々なフィルターを掛けるときに使います。
https://developer.mozilla.org/ja/docs/Web/CSS/filter
しかし、これを使用していると、iOS Safariに限って以下のような表示崩れに遭遇しました。
以下は複数の要素にdrop-shadowを適用していた際の出来事です。
Webフロントエンドをやっていてこのような崩れ方(というよりは壊れ方)をしたのが初めてで何が起きているのかさっぱりわかりませんでした。
同じような現象に遭遇している方々
https://iwb.jp/safari-css-filter-images-apply-bug/
https://vanillaice000.blog.fc2.com/blog-entry-818.html
原因
要素にハードウェアアクセラレーションが効いていないことが原因のようです。
通常、3D Transform やcss filter などが適用された要素にはGPUレイヤーが作成され、描画が高速化されます。
しかしiOSでは、iOS6よりcss filter ではGPUレイヤーが作成されず、高速化されなくなったようです。
真意はわかりませんが、GPU処理はRAMや電力を大量消費することから、省電力化のために無効にされたのではないでしょうか。
現象を確認したのがiPhone7で、XR等の最新機種では発生しなかったことや、
GPU支援がない状態で描画されることから、CPU能力に依存して発生するSafariのバグである可能性がありそうです。
対策
GPUレイヤーを作成するようSafariに促します。
方法1
.hoge {
filter: drop-shadow(0 0 8px rgba(0, 0, 0, .1));
transform: translateZ(0);
}
transformを用いることでGPUレイヤーの作成を促します。
昔から使われている方法ですね。
方法2
.hoge {
filter: drop-shadow(0 0 8px rgba(0, 0, 0, .1));
will-change: filter /* or transform */
}
本来の使い方ではありませんが、will-change を用いることでもGPUレイヤーを作成することが出来ます。
対策による副作用
GPUを使用することで確かに描画は高速化されますが、端末のリソースをたくさん割くことになるので、例えば次のようなことは推奨されません。
*,
*::before,
*::after {
will-change: all;
}
今回も本来作成されないはずのGPUレイヤーを作成しているので、良くないように思われるかもしれません。
しかし本来iOS Safari以外のブラウザでは作成されるものなので、そこまで神経質にならなくても大丈夫だと思います。
終わりに
現代のIEこと、Safariは面倒の見がいがありますね。
参考文献
http://indiegamr.com/ios6-html-hardware-acceleration-changes-and-how-to-fix-them/
https://stackoverflow.com/questions/47756158/ios-11-browsers-image-bug
https://stackoverflow.com/questions/21363230/slow-css-filters-on-iphone
https://postd.cc/css-will-change-property/