Googleが推奨する、ブラウザレンダリングに関する4つのベストプラクティスについて紹介します。
この記事は「Optimize browser rendering」を参考に書き起こしたものです。
元記事は2012年3月28日に更新されたものです。記事には5つの項目がありますが、残りの1つは情報がやや古いようなので割愛しました。
解釈が間違っている部分がありましたらどこかでつぶやいてください。
1.CSSセレクタを効率的に使用する
基本として、CSSのレンダリングは、記述されたセレクタについて、一番右端のセレクタ(キーセレクタ)から開始し、右から左方向に評価します。
で、多くの要素に一致するような非効率的なキーセレクタを避けることで、ページのレンダリングをスピードアップできるようです。
以下の子孫セレクタは非効率な例です。
キーセレクタがユニバーサルセレクタの子孫セレクタ
body * { ... }
.hide-scrollbars * { ... }
キーセレクタが要素セレクタの子孫セレクタ
ul li a { ... }
#footer h3 { ... }
* html #atticPromo ul li a { ... }
非効率な理由は、ブラウザは各要素に対して一致するか、ルート要素に到達するまでDOMツリーをトラバースして評価する必要があるためです。
次の子セレクタも同様の理由で非効率ですが、子孫セレクタよりはましなようです。
キーセレクタがユニバーサルセレクタの子セレクタ
body > * { ... }
.hide-scrollbars > * { ... }
キーセレクタが要素セレクタの子セレクタ
ul > li > a { ... }
#footer > h3 { ... }
また冗長なセレクタも不必要に評価されてしまいます。IDセレクタを利用する場合、要素セレクタを指定する必要はありません。
ul#top_blue_nav { ... }
form#UserLogin { ... }
非リンク要素への擬似セレクタは、IE7/8でレンダリング速度が落ちるようです。
h3:hover { ... }
.foo:hover { ... }
#foo:hover { ... }
div.faa :hover { ... }
1項のまとめです。
- ユニバーサルキーセレクタを避ける
- 子セレクタや子孫セレクタを避ける
- 冗長な修飾は行わない
- クラスセレクタやIDセレクタを使用する
ただし劇的に速度が上がる訳ではないようなので、既存のCSSを修正する場合は費用対効果を考えた方がよさそうです。
その他、本項では「未使用のCSSを削除すればパフォーマンスが改善する」とも書かれています。
2.CSSをHTMLドキュメントの最初の方に配置する
CSSのlink要素はhead要素の中の上部に記述します。
理由は、ブラウザはすべての外部スタイルシートがダウンロードされるまで、Webページをレンダリングブロックするためです。
スタイルシートを最初にダウンロード・解析されることで、ブラウザは徐々にページをレンダリングできます。
なお、CSSのlink要素を並べて記述すればパラレルに取得できます。以下は「Minimize round-trip times」からの引用です。
良い例
<head>
<link rel="stylesheet" type="text/css" href="stylesheet1.css" />
<link rel="stylesheet" type="text/css" href="stylesheet2.css" />
<link rel="stylesheet" type="text/css" href="stylesheet3.css" />
<script type="text/javascript" src="scriptfile1.js" />
<script type="text/javascript" src="scriptfile2.js" />
</head>
レンダリング動作
悪い例
<head>
<link rel="stylesheet" type="text/css" href="stylesheet1.css" />
<script type="text/javascript" src="scriptfile1.js" />
<script type="text/javascript" src="scriptfile2.js" />
<link rel="stylesheet" type="text/css" href="stylesheet2.css" />
<link rel="stylesheet" type="text/css" href="stylesheet3.css" />
</head>
レンダリング動作
また、@importを併用すると、パラレルに取得できるCSSがパラレルに取得できなくなる可能性があるため、「Don't use」と書かれています。
その他、style要素はhead要素に記述しないとレンダリングに影響があるように書かれています(そもそもstyle要素はHTML仕様でhead要素に記述することになっているので、body要素に記述したケースを想定して書かれているのかもしれません)。
2項のまとめです。
- CSSのlink要素はhead要素の最初の方に記述する
- @import文を使用しない
- 複数のCSSのlink要素は並べて記述する
- style要素はhead要素に配置する
3.画像のサイズを指定する
画像を表示するとき、画像のサイズ(幅と高さ)を指定することでレンダリングのパフォーマンスが向上します。
理由は、サイズを指定することで、ブラウザは画像のダウンロード前にレイアウトを算出することができ、ページ表示にかかる時間を短縮できるためです。
指定するのは、img要素のwidth属性とheight属性または、img要素の親ブロックレベル要素のいずれかです。
<img src="..." width="60" height="60" alt="..." />
または
<style>
.image {
width: 60px;
height: 60px;
}
</style>
...
<div class="image"><img src="..." alt="..." /></div>
親ブロックレベル要素に指定する場合、直接の親要素ではない要素に指定しないでください。
また、指定する場合は、画像と一致するサイズを指定します。サイズを拡大・縮小するサイズを指定するとパフォーマンスが劣化します。
3項のまとめです。
- 画像と同じサイズを指定する
- サイズは、img要素または直接の親ブロックレベル要素に指定する
4.キャラクタセット(文字セット)を指定する
当たり前すぎる内容なのであまり言及されている記事がありませんが、HTML文書にmeta要素でキャラクタセット(文字セット)を指定することで、HTMLと実行スクリプトの構文解析をすぐに開始することができます。
<meta charset="UTF-8" />
キャラクタセットの指定が必要な理由は、ブラウザが画面上へレンダリングする際に文字エンコード情報を使用するためです。
ほとんどのブラウザでは、キャラクタセットを検索しながら任意のJavaScriptを実行したり、ページを描画する前に、特定のバイト数をバッファリングします(Internet Explorer6/7/8は例外)。
レンダリングに必要なバイト数をバッファリングしたあと、デフォルトと一致しないキャラクタセットがみつかった場合、ページをレンダリングするために、ブラウザは入力を再解析してページを再描画する必要があり、この部分でパフォーマンスへの影響が発生します。