読者です 読者をやめる 読者になる 読者になる

フロントエンド開発入門編(レンダーブロッキングCSS)

Render blocking CSS | Web Fundamentals - Google Developers こちらを訳しています。コンテンツすべての著作権は原作者にあります。

レンダーブロッキングCSS

デフォルトでは、CSSはレンダーブロッキングリソースとして扱われます。つまりブラウザはCSSOMが構築されるまで、コンテンツの処理し終わったレンダリングを中止します。CSSをシンプルにして、できる限り早く届くようにし、メディアタイプやクエリを使用して、レンダリングをブロックしないようにしましょう。

前のセクションでは、DOMツリーとCSSOMツリーはクリティカルレンダーリングパスにとってレンダーツリーを構築するために必要であることを確認しました。これはパフォーマンスに重要な影響を与えます。HTMLとCSSはともにレンダーブロッキングリソースであるからです。HTMLは明らかです。というのも、DOMがなければレンダリングするものがないからです。しかし、CSSの要件はそれほど明白ではありません。CSSレンダリングをブロックすることなく、典型的なウェブページをレンダリングしようとすると、何が起こるのでしょうか?

TL;DR

デフォルトではCSSはレンダーブロッキングリソースとして扱われる。

メディアタイプやメディアクエリを使うことで、CSSリソースをノンレンダリングブロッキングとして扱うことができる。

すべてのCSSリソースは、レンダーブロッキングかノンレンダーブロッキングかに関わらず、ブラウザによってダウンロードされる。

The New York Times with CSS

The New York Times without CSS (FOUC)

上記の例では、なぜCSSが利用可能になるまで、レンダリングがブロックされるのかを説明するために、CSS有りと無しのNYTimesのウェブサイトを示しています。CSSがなければ、事実上このページは利用不可です。実際、右側の状態は"Flash of Unstyled Content"(FOUC)と呼ばれます。結果として、ブラウザはDOMとCSSOMが揃うまでレンダリングをブロックします。

CSSはレンダーブロッキングリソースであり、最初のレンダリング時間を最適化するために、できる限り早くクライアントに渡されます。

しかしながら、例えば、ページを印刷する時、あるいは大きなモニターに映し出す時といった、特定の条件下においてのみCSSスタイルが適応されるならどうでしょうか。このようなリソースでレンダリングがブロックされないなら、素晴らしいことです。

CSSの"メディアタイプ"と"メディアクエリ"を使って、このような利用法を考えることができます。

<link href="style.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">

メディアクエリはメディアタイプと特定のメディア機能の条件を調べる0個以上の式で構成されます。例えば、1つ目のスタイルシートの宣言はメディアタイプやメディアクエリを指定していないため、どんなケースでも適用されます。つまり、常にレンダーブロッキングになります。他方、2つ目のスタイルシートはコンテンツが印刷された時にのみ適用されます。レイアウトやフォントを変更しているのでしょう。このスタイルシートは最初に読み込まれた時、ページのレンダリングをブロックする必要はありません。最後のスタイルシート宣言はブラウザが実行する"メディアクエリ"を指定しています。もし条件に一致すると、ブラウザはスタイルシートがダウンロードされ処理されるまで、レンダリングをブロックします。

メディアクエリを使って、表示を、ディスプレイ表示時と印刷時との区別といった特定の使い方に合わせることができます。また、画面の向きやリサイズイベントの変化など、動的な条件に合わせることもできます。スタイルシートアセットを宣言するとき、メディアタイプやメディアクエリに注視してください。クリティカルレンダリングパスに対して大きなパフォーマンスの影響を与えます。

実践的な例で考えてみましょう。

<link href="style.css"    rel="stylesheet">
<link href="style.css"    rel="stylesheet" media="all">
<link href="portrait.css" rel="stylesheet" media="orientation:portrait">
<link href="print.css"    rel="stylesheet" media="print">
  • 1つ目の宣言はレンダーブロッキングで、すべての条件に合致します。
  • 2つ目の宣言もレンダーブロッキングです。allはデフォルトのタイプで、もしタイプを指定しないなら無条件でallに設定されます。従って、1つ目と2つ目の宣言は実際は同等です。

  • 3つ目の宣言は動的なメディアクエリを含み、ページが読み込まれたときに評価されます。ページが読み込まれたときのデバイスの向きによって、portrait.cssレンダリングをブロックするかどうかが決まります。

  • 4つ目の宣言はページが印刷されたときにのみ適応されます。従って、ブラウザ上で最初に読み込まれたときにはレンダリングをブロックしません。

最後に、"レンダーブロッキング"は、そのリソースのページの最初のレンダリングをブラウザが保留するかどうかのみについて言及することに注意してください。CSSアセットは、ノンブロッキングリソースとして優先順位は低いけれど、ブラウザによってダウンロードされます。

Authors
Ilya Grigorik
Ilya is a Developer Advocate and Web Perf Guru