Google Page Speed Insights がアドバイスしてくれる改善案に『スクロールせずに見えるコンテンツのレンダリングをブロックする JavaScript/CSS を排除する』という項目があります。
何のことを言っているのかよくわからないので放置…
という方も少なくないのではないでしょうか?
レンダリングのブロックとは一体何か?
どうやってこの問題をクリアすればよいのか?
今回は、レンダリングをブロックするCSSの最適化について、Googleも推奨している loadCSS 関数を用いた解決策を紹介します。
CSSの配信を最適化すると、ページの表示速度が目に見えて改善されることが多いので、ぜひ対策方法を知っておきましょう。
目次
スクロールせずに見えるコンテンツのレンダリングブロックとは
レンダリングとは、ブラウザがWebページを表示するために行う一連の描画処理のことです。
一般的に、スタイルシートは外部ファイル化して、headタグ内のlinkタグでファイルを読み込んでいます。
<head>
<title>ページタイトル</title>
<link rel="stylesheet" href="css/style.css">
</head>
CSSはページのレンダリングに必要なため、ブラウザがCSSを解析して利用できる準備が整うまで、ブラウザのピクセル上に描画をしません。これがレンダリングブロックです。
これは、そもそもCSSはレンダーブロッキング リソースであることを意味しています。
ですので、CSSによるレンダリングのブロック自体を回避することはできないことになります。
Page Speed Insights では、『スクロールせずに見えるコンテンツ』という条件付きでレンダリングブロックを改善するようアドバイスしている点に注目してください。
CSSファイルには、ページまたはサイト全体についてのスタイルが定義されているはずです。
そこには、スクロールしてから見えるコンテンツのスタイルも含まれています。
つまり、スクロールせずに見えるコンテンツ以外のCSSも読み込んでる分だけレンダリングが遅くなっているよ、と忠告をしてくれているのです。
レンダリングブロックCSSの解決策
CSSはレンダーブロッキングリソースであることと、スクロールしてから見えるコンテンツのCSSがページの表示速度に影響していることがわかりました。
この問題をクリアして、Page Speed Insights のスコアを上げるにはどうしたらよいでしょうか?
その解決策として、段階的にCSSを読み込むようにします。
ページにアクセスした時にスクロールしないで見える表示領域のことを Above The Fold と言います。ファーストビューなどとも言いますね。
対して、スクロールして表示されるコンテンツの領域は Below The Fold と言います。
Above The Fold に関係するCSSだけを先に読み込み、後から残り (Below The Fold) のCSSを処理させることで、CSSの配信とレンダリングを最適化させます。
最適化には次の2つの修正が必要です。
- クリティカルCSSを抽出してインラインでHTMLのheadタグに記述する
- クリティカルCSS以外のCSSはレンダリングに干渉させずに読み込むようにする
ここからは、具体的な実装手順と解説をしていきます。
実装する時は、いつでも元に戻せるように変更を加えるファイルのバックアップをとっておきましょう。
クリティカルCSSの抽出
クリティカルCSSとは、クリティカルレンダリングパスに必要なCSSのことです。
クリティカルレンダリングパス (Critical Rendering Path) とは、ブラウザの最初のレンダリングが行われるまでの処理のことです。
ここでは『スクロールせずに見えるコンテンツのレンダリング』と同義と考えておいてください。
クリティカルCSS、すなわち、Above The Fold のコンテンツに必要なスタイルシートの記述だけを抽出します。
手軽に扱えるオンラインツールで Critical Path CSS Generator があるので、こちらを使うことにします。
表示されている番号順通りに操作していきます。
- 最適化したいページURLを入力
- 1のページで読み込んでいるCSSのテキストを全てコピーしてペースト
- [Create Critical Path CSS]ボタンをクリック
クリティカルCSSのテキストが生成されるのでコピーしておきます。
コピーしたコードは、headタグ内にインラインで記述します。
style
タグで囲って、CSSを読み込むlinkタグの直前に挿入します。
<head>
<style>クリティカルCSSコード挿入…</style>
<link rel="stylesheet" href="css/style.css">
</head>
元のCSSファイルとクリティカルCSSが違うディレクトリにある場合は、ファイルの位置関係が変わるので注意してください。
画像ファイルなどを相対パスで参照している場合にコードの修正が必要です。
プロパティの例: background-image: url("images/image.jpg");
クリティカルCSS内の相対パスを変更するか、絶対パス (完全URL) に書き換えましょう。
link rel=”preload” の記述
続いて、linkタグのrel属性の値を rel="preload"
に変更し、as="style"
を追記します。
<style>クリティカルCSSコード挿入…</style>
<link rel="preload" href="css/style.css" as="style">
preload は、href属性で指定したURLのコンテンツを先読みするための指定です。
これにより、レンダリングブロックを回避しながらCSSを読み込むことができます。
これで対応完了としたいところですが、残念ながらまだ問題が残っています。
参考: rel=”preload” によるコンテンツの先読み
rel=”preload” 未対応ブラウザの問題
link rel=”preload” の機能をサポートしいないブラウザがあります。
上図の赤色のブラウザ・バージョンが未対応のブラウザです。
特に、Internet Explorer 11 の日本でのシェアは、開発終了となった今でもおおよそ16%もシェアを持っているため、見過ごすわけにはいきません。
ブラウザのシェアが変化するまでは、rel=”preload” 未対応ブラウザにもCSS最適化を適用するため、JavaScriptを使って擬似的に対応していきます。
loadCSS の導入
preload 機能の代用として filament group が提供する loadCSS という JavaScript を利用させてもらいます。
loadCSS: A function for loading CSS asynchronously
その中から、今回利用する cssrelpreload.js のコードをコピーしておきます。
headタグ内のスタイルシートに関する記述を次のように変更します。
<head>
<style>クリティカルCSSコード</style>
<link rel="preload" href="css/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="css/style.css"></noscript>
<script>/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
csspreload.jsコード挿入…
</script>
</head>
linkタグに onload="this.onload=null;this.rel='stylesheet'"
を追加します。
JavaScriptをオフにしている環境では通常のスタイルシートを読み込んでもらうため、noscript
タグで rel="stylesheet"
のlinkタグを囲みます。
読み込むCSSファイルが複数ある場合は、link rel=”preload” タグとそれに対応するnoscriptタグを1セットとして、必要な分だけ記述します。
script
タグに、コピーした csspreload.js のコードをペーストします。
最後に、実際のページを確認して表示崩れがないかなどを確認します。
Page Speed Insights で検証する
問題なく実装できたら Page Speed Insights で検証しましょう。
検証したいURLを入力して分析を開始します。
『スクロールせずに見えるコンテンツのレンダリングをブロックするJavaScript/CSS を排除する』が無事に最適化済みの項目に移動しました。
bodyタグ内でのCSSの読み込みとFOUC現象
CSSファイルをbodyタグの最後の方に読み込ませて、クリティカルレンダリングパスへの影響を回避する、という方法もあるようです。
確かに、bodyタグ内でCSSを読み込むことは、HTMLの仕様上許可されています。
しかしながら、CSSを後から読み込ませるとFOUC現象が起こります。
FOUCとは Flash of Unstyled Content の略で、和訳すると『スタイル未指定コンテンツのちらつき』という意味になります。
これは、ブラウザがHTMLを上から順に読み込んで、レンダリングを開始していくために起こる現象です。
CSSの記述が発見されないままレンダリングしていたら、後になってCSSファイルを発見したので再度コンテンツをレンダリングしなおす、ということがブラウザ内部で起きているのです。
現在のブラウザは優秀なので、たとえbodyタグの最後にlinkタグでCSSを読み込んだとしても、FOUCが起こりにくいかもしれません。
しかし、モバイル回線の通信が安定しない環境下などでは、FOUCが起こることもあります。
また一般的に、headタグでCSSを読み込む方がトータルのページ・ロード時間は短くなります。
ですので、linkタグはbodyタグの最後ではなく、headタグ内に記述する方が良いでしょう。
CSS配信最適化で体感速度アップ
レンダリングブロックをするCSS配信の最適化について解説しました。
デメリットとしては、スタイルシートに変更があった場合に、クリティカルCSSについてもチェックや修正をしなくてはならないので、手間が増えてしまいます。
それと、ページの種類によってデザイン自体が異なることもあるので、全ページのCSSを最適化しようとすると、作業の繰り返しが発生します。
一方で、レンダリングブロックCSSの最適化のメリットは、わかりやすく効果的です。
Webの表示スピードに関する改善は、体感ではわかりにくい施策もありますが、クリティカルレンダリングパスの改善は、体感でも表示が速くなったと感じられることが多いからです。
表示の速いサイトという好印象をユーザーに持ってもらえれば、離脱率の減少や回遊率の改善、コンバージョン率アップも期待できます。
重要なページに実装するなど、管理コストとのバランスも考えながら最適化を検討しましょう。
コメントをどうぞ