Google Page Speedの記事から始まってしまったサイト高速化関連記事。
今回は、効率の良いスタイルを書くために、ブラウザがHTMLを解析してDOMツリーをつくり、そこにスタイルをあてていく過程を見ていきましょう。
基本的な手順がわかると、どういったcssの書き方が効率が良く、どういった書き方では迂遠であったり冗長であったりするのかが、理解できるようになると思います。
この記事は、Google Page Speedの”“および、Mozillaの”Writing Efficient CSS for use in the Mozilla UI“などを元に書いています。そのため、この仕組みは主にMozillaエンジンについてです。IEやWebKitでは若干異なった動作をする部分もあるようです。
マッチングの回数
ブラウザは、読み込んだHTMLをパースしてDOMツリーを作成します。
その後、ツリーを辿りながらそれぞれの要素について、各スタイルが合致するかどうかを検証することになります。検証はルールのグルーピング(後述)などにより効率化はされていますが、基本的には全ての要素を駆動表に、全てのスタイルルールを検証する作業になります。つまり、端的には次のような計算数分だけ、マッチングが行われるわけです。
HTML中の全要素数 × スタイル上のルール数
例えば、次のようなシンプルな文書があったとします。
タイトル
......
この中に、要素は5つ(body, h1, div x 3)あります。スタイルは3つです。5つの各要素に対して3つのルールがマッチするかを検証するわけですから、マッチング数としては 5 x 3 となり、計15回のマッチングが行われる計算になります。
マッチングの詳細
では、今度は各マッチングを見ていきます。
まず”Keyセレクタ”という言葉を覚えてください。これは、単純に「ルールの一番右側にあるセレクタ」を指します。例えば次のようなスタイルがあった場合、
#id { ... } .class div, .class p { ... } div.class form input[checked="checked"] { ... }
Keyセレクタは上から順に、#id、divとp、input[checked="checked"]です。
このKeyセレクタが次のいずれに該当するかで、スタイルルールをまず大きく4つに分類します。
-
ID Rules
KeyセレクタがIDであるもの。button#backButton { } #urlBar[type="autocomplete"] { } treeitem > treerow > treecell#myCell:active { }
-
Class Rules
Keyセレクタがクラス指定であるもの。button.toolbarButton { } .fancyText { } menuitem > .menu-left[checked="true"] { }
-
Tag Rules
Keyセレクタがタグ指定であるもの。td { } treeitem > treerow { } input[type="checkbox"] { }
-
Universal Rules
Keyセレクタが、つまり上記3つのいずれにも当てはまらないもの。[hidden="true"] { } * { } tree > [collapsed="true"] { }
このようなグループ分けをした上で、マッチングは該当要素に合致するかどうかを、ルールの右(Keyセレクタ)から順に左方向に確認していきます。合致しなくなったところで検証を止めます。
具体的に見てみましょう。
次のようなスタイルがあったとします。
div.cls fieldset > input { ... }
HTMLは、次のようにします。
ここで6行目のcheckboxを、前述のスタイルルールにマッチングしてみます。
- Keyセレクタである”input”がタグなので、このルールはTag Rulesに分類されています。この要素はまずTag Rules中のinputにマッチするかを確認し、検証を始めます。
- ひとつ左に行くと、これは「1つ親の要素がfieldsetである」という意味です。そこでDOMツリーでひとつ上を確認(5行目)すると、確かにfieldsetです。
- そこで次のルールを確認します。次は「先祖にclsという名前のクラスを持つdiv要素があること」です。DOMツリーを順に辿っていくと(4→3→2行目)、該当するものが見つかりました。
- 全てのルールに合致したので、このスタイルを適用します。
では次に、次のようなルールを検証してみましょう。
#id { ... }
これは当然、ID Rulesにカテゴライズされています。
- idというidを持つ要素であるので、合致する
終わりです。
これは極端な例ですが、スタイル指定の効率の良し悪しが想像つくと思います。
次は、具体的に効率の悪いスタイル記述を挙げてみます。そういった記述を極力避けることで、スタイルの適用を高速化することができます。
Related posts: