業務の合間に制作部の社内勉強会にちょこちょこ参加していろいろ学んだのでメモ。
ここではCSSの最適化について。
* ブラウザはCSSをどう解釈している?
ルールを照合するとき、右端のセレクタから調べ始めて、順に左のセレクタを調べていく。
ということは、
1 |
#contents > li { font-weight: bold; } |
のようなルールの場合「contents という id を持つ要素を探して、その直接の子要素が li 要素かどうかを調べる」ではなく「すべての li 要素について、その直接の親要素が contents という id を持つかを調べる」となり高コストです。子孫セレクタの場合はさらに高くつき、
1 |
#contents a { color: #0099ff; } |
のようなルールの場合「すべての a 要素について、contents という id を持つ祖先要素をツリー構造をさかのぼって探す」ということになります。子供セレクタであれば1つ上の階層のノードだけ調べれば済みますが、子孫セレクタの場合はさらにさかのぼって探索しなければなりません。Win IE6対応を無視してもいいなら、子孫セレクタから子供セレクタに置き換えた方がいいです。ただ、その子供セレクタも高コストには違いないので、それを1つの class に置き換えます。
1 |
#contents > li > a { font-weight: bold; } |
ではなく
1 |
.list-anchor { font-weight: bold; } |
のように要素と関連づけた名前で class を作ってスタイルを適用させることで、探索時間をさらに短くすることができます。
* ユニバーサルセレクタについて
1 |
* { margin: 0; padding: 0; } |
一時期よく使われていたユニバーサルセレクタは最近では見かけなくなりました。社内の制作さんは、「パフォーマンスが悪くなる」という点よりも「ブラウザのデフォルトのスタイルを活かす」という点の方を重視しているみたいでしたが、ここまで述べてきた内容からパフォーマンスも相当悪くなるのは明らかです。その点について stevesouders.com さんが検証していました。
CSS Selectors: Universal
上述の子供セレクタや子孫セレクタによる読み込み時間の違いは小さなものですが、ユニバーサルセレクタを使用した場合はケタ違いに読み込みが遅くなっています。
* リフロー時間について
ブラウザがスタイルを適用し要素をレイアウトするのにかかる時間をリフロー時間と呼ぶそうです。スタイルの適用はページの読み込み時のみとは限りません。というのは、最近のWebサイトはJavascriptを多用していて、リッチな表現を行うためにDOM要素の style プロパティを頻繁に書き換えている例が多く見られます。
1 2 3 4 5 6 7 |
document.getElementById("id").style.property="value" // 例 document.getElementById("contents").style.fontSize = "larger"; // 実際は上記のような処理がラップされたjQueryなどのライブラリを利用している場合が多い // 制作工数とパフォーマンスのバランスを考えて使う $("#contents").css("border", "1px solid #333333"); |
style プロパティを書き換えるとブラウザはその度にルールを照合しなおしています。もし、DOM要素が body などの多くの子孫を持つ要素の場合、効率の悪いセレクタがあるとページの反応が遅くなってしまいます。ページの読み込み時だけでなくWebアプリケーションがユーザと情報をやりとりしている間の動作に及ぶ影響にも注意することが重要です。
参加したのは新卒向けの勉強会だったので得られたのはこの程度の内容ですが、通常業務でも制作さんといっしょに仕事する機会ができたので、もう少し深い部分も聞いてみたいと思います。
One thought