Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@mt877

レンダリングブロックに配慮したリソースの読み込み(CSS編)

はじめに

こちらの記事はレンダリングブロックに配慮したリソースの読み込み(レンダリングの基本編)の続きです。
前述の記事を読んでおくと、当記事の内容も理解しやすいかもしれません。

やるべきこと

CSSファイルが読み込まれるとパース後にCSSOM(CSS版のDOMのようなもの)の構築が行われます。
CSSOMの構築中はJavaScriptの実行やページのレンダリングがブロックされます。(DOMの構築はブロックしません。)
しかし、以下の対策を行うことでこのような問題が解消されます。

1. CSSを非同期で読み込み
2. クリティカルCSSをインラインで記述

具体的にどのような記述をすれば良いのか紹介していきます。

CSSを非同期で読み込み

CSSを非同期で読み込むとCSSOMの構築も非同期になり、JavaScriptの実行やレンダリングがブロックされるといった問題が解消されます。
CSSの非同期読み込みには2パターンあります。

注意
非同期の特性上CSSの適用遅れが発生し、スタイルが適用されていないコンテンツが表示されることがあります。(いわゆるFOUC)
またJavaScriptにはCSSOMを取得・変更する機能があるため、原則としてCSSOMの構築が完了してから実行されるようになっています。
CSSやJavaScriptのどちらか、または両方を非同期で読み込むと実行順序が担保できなくなってしまい、JavaScriptでスタイルの制御をしている場合などは処理に影響が出る可能性があります。
レンダリングブロック対策に注力するあまり正しい処理が行われないのは本末転倒なので状況によって使い分けてください。

rel=preload属性を使った非同期読み込み

<head>
  <link rel="preload" href="foo.css" as="style">
</head>
<body>...</body>

特徴

  • IEなど一部ブラウザは非対応のためpolyfillが必要になります。

media・onload属性を使った非同期読み込み

<head>
  <link rel="stylesheet" href="foo.css" media="print" onload="this.media='all'">
</head>
<body>...</body>

特徴

  • media属性をprintに設定することで非同期でロードするようになります。
  • そのままでは印刷の際にしかスタイルが適用されないためonload属性を使い、読み込み完了後にmedia属性をallに変更します。
  • IEなどでも使用可能です。

クリティカルCSSをインラインで記述

ファーストビューに必要なCSSをインラインで、それ以外のCSSを非同期で読み込むようにします。
これによってFOUCを抑えつつ、CSSOM構築に伴うレンダリングブロックの影響を最小限にすることができます。

<head>
  <style>/* クリティカルCSSを記述 */</style>
  <link rel="preload" href="foo.css" as="style">
</head>
<body>...</body>

特徴



以上がレンダリングブロックに配慮したCSSの読み込み方法になります。
また、レンダリングブロックの視点から考えたアンチパターン・おすすめできない方法についてもまとめました。

アンチパターン

サイズの大きいCSSファイルをそのまま読み込み

<head>
  <link href="foo.css" rel="stylesheet">
  <script src="foo.js"></script>
</head>
<body>...</body>

推奨しない理由

  • ファイルの読み込みからCSSOMの構築が完了するまでレンダリングがブロックされます。(DOMの構築はブロックしません。)
  • 読み込みが完了するまでは何も表示されないため、クライアントの回線状況によってはUXに影響が出ます。
  • CSSの直後に読み込んでいるJavaScriptは直前までのCSSOM構築が完了してから実行されます。(scriptタグにasync・defer属性を付与した場合はこの影響を受けず非同期で実行されます。)
  • インラインCSSでも同様です。

<body>内で読み込み

HTML5.2からbody内でも外部CSSを読み込めるようになりました。
※特に有用な場面が思いつきませんでしたがピックアップしました。

<head>...</head>
<body>
  <p>テキスト1</p>
  <link href="foo.css" rel="stylesheet">
</body>

推奨しない理由

  • ファイルの読み込みからCSSOMの構築が完了するまでレンダリングがブロックされます。(DOMの構築はブロックしません。)
  • 読み込みが完了(CSSOM構築)するまでは何も表示されないため、クライアントの回線状況によってはUXに影響が出ます。

CSS-injectedでの読み込み

CSS-injectedは外部リソース読み込みのソースコードを出力するインラインJSです。(以下の記述を参照)

CSS-injected 実行前

<head>
  <script>
    const link = document.createElement('link');
    link.href = 'foo.css';
    link.rel = 'stylesheet';
    const head = document.getElementsByTagName('head')[0];
    head.appendChild(link);
  </script>
</head>
<body>...</body>

CSS-injected 実行後

<head>
<link href="foo.css" rel="stylesheet">
</head>
<body>...</body>

推奨しない理由

  • 読み込みとCSSOM構築が非同期で行われますが、JavaScriptの実行からCSSの読み込み・CSSOM構築が完了するまではスタイルが適用されていないページが表示されます。

レンダリングブロック対策のまとめとポイント

  • 外部CSSは非同期で読み込む。
  • サイズの大きいCSSファイルを同期的に読み込まない。
  • クリティカルなCSSはその他のCSSと切り離してインラインで記述する。
  • 非同期の読み込みはJavaScriptの処理も考慮して指定する。

参考URL

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
mt877

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?