レンダリング ブロック CSS

公開日: 2014 年 3 月 31 日

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

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

  • デフォルトでは、CSS はレンダリング ブロック リソースとして扱われます。
  • メディアタイプやメディアクエリを利用すると、一部の CSS リソースを非レンダリング ブロックとして指定することができます。
  • CSS リソースは、ブロック リソースであるか非ブロック リソースであるかにかかわらず、すべてブラウザでダウンロードされます。
NYTimes と CSS
CSS ありの The New York Times
CSS なしの NYTimes
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 個以上の式(式は特定のメディア機能の条件をチェック)で構成されます。たとえば、先ほどのスタイルシートの宣言ではメディアタイプやメディアクエリが指定されていないため、すべての場合に適用されます。つまり、常にレンダリング ブロックとなります。一方で 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 アセットもブラウザによってダウンロードされます。

フィードバック