ブラウザのCSS解釈方法についての衝撃事実

More than 1 year has passed since last update.

CSSのパフォーマンスについて調査していたところ、衝撃の事実を知りました。

それは、


「CSSセレクタは右から左へと照合される」


らしいです。


今までの私の見解

.sample table td {

color: red;
}

上記のようなコードがあったとき、以下の順序でブラウザは解釈・実行していると思っていました。

  1.  sampleクラスを見つける

  2.  1の子孫のtable要素を見つける

  3.  2の子孫のtd要素を見つける

  4.  文字色を赤くする


正しい見解

.sample table td {

color: red;
}

上記のようなコードがあったとき、以下の順序でブラウザは解釈・実行しているらしいです。

  1.  全てのtd要素を見つける

  2.  1の先祖要素にtable要素が存在するかを確認

  3.  2のtable要素の先祖要素にsampleクラスが存在するかを確認

  4.  文字色を赤くする

このように、CSSセレクタは右から左へと照合されていきます。

※一番右側のセレクタは、キーセレクタと呼ばれるらしいです


何が問題か?

例えば、以下のようなHTMLコードがあったとします。

上記のCSSコードでsampleクラス配下の表の文字色を赤くしようとすると、まずDOM内の全てのtd要素を見つけ、さらにtable要素・sampleクラスの存在確認をしようとします。

sample2クラス配下の表は文字色が黒のままで良いので、sample2クラス配下のtd要素は、本来見つけなくて良いことになります。

これは、明らかなコストの無駄です。

sample2クラス配下のtd要素が爆発的に増えれば、パフォーマンス問題につながる可能性があります。

<!-- 文字色を赤くしたい表 -->

<div class="sample">
<table>
<tr>
<td>hoge</td>
<td>hogehoge</td>
</tr>
<tr>
<td>fuga</td>
<td>fugafuga</td>
</tr>
</table>
</dvi>

<!-- 文字色は黒のままで良い表 -->
<div class="sample2">
<table>
<tr>
<td>hoge</td>
<td>hogehoge</td>
</tr>
<tr>
<td>fuga</td>
<td>fugafuga</td>
</tr>
</table>
</div>


どのようにすべきだったか

既にお分かりかと思いますが、念のため記載しておきます。

やはり、文字色を赤くしたいセルにだけ、赤くするクラスを付与するのが一番良いです。

.red {

color: red;
}

<!-- 文字色を赤くしたい表 -->

<div class="sample">
<table>
<tr>
<td class="red">hoge</td>
<td class="red">hogehoge</td>
</tr>
<tr>
<td class="red">fuga</td>
<td class="red">fugafuga</td>
</tr>
</table>
</dvi>

<!-- 文字色は黒のままで良い表 -->
<div class="sample2">
<table>
<tr>
<td>hoge</td>
<td>hogehoge</td>
</tr>
<tr>
<td>fuga</td>
<td>fugafuga</td>
</tr>
</table>
</div>


結論


  • キーセレクタはパフォーマンス問題に直結する可能性がある

  • キーセレクタは出来る限り絞り込む(無関係のDOMをマッチさせないようにする)

  • キーセレクタをどれだけ絞り込むかでコストが左右される


参考サイト

CSS の適用について

http://d.hatena.ne.jp/oknknic/20110716/1310835176

Webkit と Firefox のレンダリングの仕組み

https://www.html5rocks.com/ja/tutorials/internals/howbrowserswork/#Manipulating_the_rules_for_an_easy_match

レンダリングについて

https://qiita.com/mikimhk/items/7cfbd6c94d0f3d7aa51f#3-rendering