📏

widthやheightをアニメーション化してはいけない

2022/05/09に公開

widthやheightをアニメーション化してはいけない

width,heightのアニメーションについて、以下のように記述しているサイトがありました。

Web上でアニメーション化する最初のルール:height,widthをアニメーション化しないでください。
https://css-tricks.com/animating-css-width-and-height-without-the-squish-effect/

CSSwidthとheightプロパティをアニメーション化できると非常に便利です。残念ながら、現時点では、ブラウザを苦痛で悲鳴を上げるための確実な方法です。
https://pqina.nl/blog/animating-width-and-height-without-the-squish-effect/

英語らしいユニークな言い回しで最悪の手段だということが十分に伝わります。

なぜいけないのか

結論から言うと、 リフローを発生させてしまい、処理を重くしてしまう からwidthやheightをアニメーション化はしてはいけないそうです。
ここから先はリフローの解説と、解決策を記述します。

そもそもリフローとは

ブラウザでHTMLとCSSが読み込まれてからWebページを表示する際はブラウザレンダリングという処理が行われます。

https://www.yoheim.net/blog.php?q=20140703

s300.png

ブラウザレンダリングの詳細はこの記事では書きませんが、リフローはこのブラウザレンダリングの工程の1つで [4] 、ドキュメント内の要素の位置とジオメトリを計算する処理のことを指します。
width,heightをアニメーション化すると、アニメーションをつけた要素の親要素または子要素のサイズにも影響を及ぼす可能性があり、要素の再計算をする必要が出てきます。つまり、上図の [4][5] の工程を再び行わなければならないということです。
これがパフォーマンスを下げる原因になります。

解決策

パフォーマンスの高いアニメーションを実行するには、transformまたはopacityプロパティを使用する必要があります。transformプロパティは、要素を画面に描画(Paint)する前に、要素のテクスチャを直前に更新するようにGPUに指示します。GPUはピクセルの処理に非常に優れているため、高速な処理を実現できます。

ですが、この処理にも欠点があります。要素の内容ではなくピクセルのみを操作するという点です。要素の他のすべての情報がなくなっていることを忘れないでください。この違いがborder-radiusプロパティなどでよくわかります。transformを使用すると要素の角が単純に引き延ばされるあるいは縮ませられるだけになってしまいます。

https://pqina.nl/blog/animating-width-and-height-without-the-squish-effect/

おまけ

icon.png
CSS Triggersというサイトでは、どのプロパティにLayoutやPaintが発生するか書いてあります。
上の画像の例では、widthはLayoutやPaintがトリガーされてしまうことが分かります。

https://csstriggers.com/

Discussion