リフロウとリペイント:CSSがjavascriptのパフォーマンスの足をひっぱっている?(を読んだメモ)

Stubbornella ? Blog Archive ? Reflows & Repaints: CSS Performance making your JavaScript slow?
上記エントリをテキトーに解釈して要点をメモってみた。

リペイント(repaint)

要素のスキン見た目、が変化したときに発生。
ただしレイアウトには影響しない。

  • outline
  • visibility
  • background color

など、
Operaのレポートによると、リペイントは処理コストが高くつくらしい。
なぜなら、DOMツリー内の他のノード(要素)全ての見た目について検証しなければいけないから。

リフロウ(reflow)

リフロウはパフォーマンスにとってさらに重要。
なぜなら、それによってページの一部(あるいは全体)のレイアウトの変更を引き起こすから。

たとえば、下のようなHTMLがあったとした場合、

<body>
<div class=”error”>
	<h4>My Module</h4>
	<p><strong>Error:</strong>Description of the error…</p>
	<h5>Corrective action required:</h5>
	<ol>
		<li>Step one</li>
		<li>Step two</li>
	</ol>
</div>
</body>

<p>要素の変更はその子要素であるの<strong>要素のリフロウを引き起こす。
また、ブラウザによってはその祖先要素である<div>や<body>のリフロウを引き起こす場合もある。
さらに、後続の要素である<h5><ol>要素のリフロウも引き起こす。

このように、リフロウの連鎖によってページ全体の再描画を引き起こしパフォーマンスが低下する。

リフロウを引き起こす原因

困ったことに、たくあんある orz

  • ウィンドウのリサイズ
  • フォントの変更
  • スタイルシートの追加・削除
  • コンテントの変更(inputボックスへの文字の入力とか?)
  • CSS擬似クラスの有効化(:hoverとか)
  • class属性に対する操作
  • スクリプトによるDOMの操作
  • offsetWidth, offsetHeightの再計算
  • style属性への値の設定

参考:Notes on HTML Reflow

リフロウを避けるあるいはその影響を最小化する方法

可能な限り末端に近いほうのノードで変更する

そうすることによって、リフロウの影響範囲を限定することができる

styleプロパティによる変更を避ける

styleのプロパティ1つ1つに対する変更に対してリフロウが発生する。
その代わりに、classを別途用意してclassの切り替えとすることで、1度のリフロウで済ませることができる。

アニメーションは position fixed または absolute の要素で

positionがfixedまたは、absoluteの要素の要素は他の要素のレイアウトに影響を与えない。リペイントは発生するが、リフロウに比べたらコストは低い。

滑らかさと速度を天秤にかける

1ピクセルづつ移動するより、3ピクセルづつ移動させるほうがCPUにやさしい。見た目は悪くなるけど...

レイアウト目的でのtableの使用を避ける(または table-layout を fixed に設定する)

テーブル全体のレイアウトはテーブルの最後の行を表示するまで確定できない。
例えば最後の行のセルの幅がそれ以前の行の幅より大きくなったとしたら、テーブル全体の幅が変更されてしまう。
そのため、テーブルのレンダリングはコストが高い。
それがテーブルをレイアウト目的で使ってはいけない理由。
テーブルを使う場合には、table-layout を fixed に設定した方がよい。
それによって、ブラウザは最後までテーブルの要素を読み込まなくても、レイアウトを確定することができる。

CSS内でのjavascript式の使用を避ける(IEのみ)

css内での式の利用は非常にコストが高い。
それはリフロウのたびに式の評価が必要になるから。そしてその評価の結果がリフロウを発生させ、それにともなって式の評価を行い... と連鎖する。
CSSでjavascripの式をつかっちゃダメ、ゼッタイ。

以上、
テキトーなんで注意。
ちゃんと理解したい人は原文を読むことをお勧めします。

参考になりそうなリンク

上記エントリから参考になりそうなリンクをピックアップ

stubbornella's reflow Bookmarks on Delicious
Efficient JavaScript - Opera Developer Community
Notes on HTML Reflow