レンダリング ブロック CSS

公開日: 2014 年 3 月 31 日

デフォルトでは、CSS はレンダリング ブロック リソースとして扱われます。つまり、ブラウザは、CSSOM の構築が完了するまで、処理済みコンテンツのレンダリングを保留します。CSS のサイズを小さくし、できるだけ早く配信されるようにし、メディアタイプやメディアクエリを利用してレンダリングのブロックを解除してください。

レンダリング ツリーの構築で、クリティカル レンダリング パスでは、レンダリング ツリーを構築するために DOM と CSSOM の両方が必要であるということを説明しました。このことは、パフォーマンス上重要な意味を持ちます。HTML と CSS の両方がレンダリング ブロック リソースです。DOM がなければレンダリングできないのですから HTML については理解できます。しかし、CSS が必要である理由はわかりにくいかもしれません。CSS によるレンダリングのブロックを回避して、一般的なページをレンダリングするとどうなるでしょうか。

概要

  • デフォルトでは、CSS はレンダリング ブロック リソースとして扱われます。
  • メディアタイプやメディアクエリを利用すると、一部の CSS リソースを非レンダリング ブロックとして指定することができます。
  • CSS リソースは、ブロック リソースであるか非ブロック リソースであるかにかかわらず、すべてブラウザでダウンロードされます。
CSS ありの The New York Times
CSS なしの The New York Times(FOUC)

上記の例では、CSS ありと CSS なしで New York Times のウェブサイトを表示しています。これを見ると、CSS の準備が整うまでレンダリングがブロックされる理由がわかります。CSS がない場合、ページは実質的に利用できません。右側のような状態は、FOUC(Flash of Unstyled Content)と呼ばれます。ブラウザは、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 がレンダリング ブロックになるかどうかが決まります。
  • 最後の宣言は、ページが印刷される際にのみ適用されます("print")。したがって、ページが最初にブラウザに読み込まれる際にはレンダリング ブロックにはなりません。

最後になりますが「レンダリング ブロック」とは、ブラウザが、該当するリソースでページの初回レンダリングを保留する必要があるか否かということだけを指しています。いずれの場合も、非ブロック リソースで優先順位が低い CSS アセットもブラウザによってダウンロードされます。

フィードバック

Image for: フィードバック