CSSの実装方法を少し改善するだけで、Webページの読み込み・表示を最適化するテクニックのまとめ
Post on:2021年6月29日
CSSの記述方法やレイアウトの構築方法で、ページの表示速度、読み込み時に発生するレイアウトのずれ、Webフォントの表示、CSSアニメーション、アクションを起こした時の反応の速度など、ウェブバイタルに大きな影響を与えます。
ウェブバイタル(Web Vitals)を最適化するためのCSSのテクニックを紹介します。
CSS for Web Vitals
by Katie Hempenius, Una Kravets
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
CSSの記述方法やレイアウトの構築方法で、コアウェブバイタル(Core Web Vitals)に大きな影響を与えます。特にCumulative Layout Shift (CLS) と Largest Contentful Paint (LCP) に当てはまります。
用語解説
ウェブバイタル(Web Vitals)とは、Googleが設定しているサイトの健全性を示す重要指標です。中でも中心となる3つの要素は、コアウェブバイタル(Core Web Vitals)と呼ばれています。
-
- Cumulative Layout Shift (CLS)
- ページの読み込み時に発生するレイアウトのずれ、視覚的な安定性を測定する指標です。
-
- Largest Contentful Paint (LCP)
- ページの表示速度、読み込みにかかる時間を測定する指標です。
-
- First Input Delay(FID)
- アクションを起こした時の反応の速度、インタラクティブ性を測定する指標です。
この記事では、ウェブバイタル(Web Vitals)を最適化するためのCSSのテクニックを紹介します。これらの最適化は、ページのさまざまな側面(レイアウト・画像・フォント・アニメーション・読み込み)に分けて解説します。その過程で、サンプルページの改善についてもご解説します。
レイアウトのCSSを改善
DOMへのコンテンツ挿入
周囲のコンテンツがすでに読み込まれた後にコンテンツを挿入すると、ページ上の他のすべてが押し下げられます。これにより、レイアウトシフト(レイアウトのずれ)が発生します。
例えば、Cookieの通知パネルです。特にページの上部に表示される通知パネルは、この問題の一般的な例です。他にも広告や埋め込みなどの要素が読み込まれる際に、このようなレイアウトシフトを引き起こします。
原因を特定する
サンプルページをブラウザで表示し、Lighthouseでレポートを作成します。レポート内の「Avoid large layout shifts」にレイアウトシフトの原因となった要素が表示されます。このサンプルページでの結果は、下記の通りです。
Lighthouseの「Avoid large layout shifts」
Cookieの通知パネルがこのリストに入っていないのは、ロード時にシフトしないからです。むしろ、ページの下にある要素(つまり、div.heroとarticle)がシフトする原因です。レイアウトシフトの特定と修正方法に関する詳細は、Debugging Layout Shiftsをご覧ください。
注: Lighthouseは「ページロード」イベントまでのページのパフォーマンスを分析します。Cookie・バナー・広告などのウィジェットは、ページが完全に読み込まれるまで読み込まれないことがあります。このようなレイアウトシフトは、Lighthouseがフラグを立てていなくても、ユーザーに影響を及ぼします。
修正方法
Cookieの通知パネルは、絶対配置または固定配置でページの下部に配置します。
Cookieの通知パネルは下部に配置
修正前
1 2 3 4 |
.banner { position: sticky; top: 0; } |
修正後
1 2 3 4 |
.banner { position: fixed; bottom: 0; } |
レイアウトシフトを修正する別の方法は、画面上部にCookieの通知パネルを表示するスペースを確保しておくことです。この方法も同様に効果があります。詳しくは、Cookie notice best practicesをご覧ください。
注: Cookieの通知パネルは、ロード時にレイアウトシフトを引き起こす複数のページ要素の1つです。他のページ要素をより詳しく見るために、以降のステップでは、Cookieの通知パネルを表示しません。
画像のCSSを改善
Largest Contentful Paint (LCP)要素
画像は一般的に、ページ上のLargest Contentful Paint (LCP)要素となります。LCP要素になり得る他のページ要素は、テキストブロックや動画のポスター画像です。LCPは、LCP要素がロードされる時間によって決まります。
注意しなければならないことは、ページ上のLCP要素はページが最初に表示されたときにユーザーに見えているコンテンツによって、ページの読み込みごとに変化するということです。例えば、サンプルページではCookie通知の背景、ヒーロー画像、記事テキストなどがLCP要素の候補となります。
LCP要素になり得るページ要素
サンプルページではCookie通知の背景画像は実際に大きな画像です。LCPを改善するには、効果を出すために画像を読み込むのではなく、CSSグラデーションで描画するとよいでしょう。
修正方法
.bannerのCSSを、画像ではなくCSSグラデーションに変更します。
ビフォー
1 |
background: url("https://cdn.pixabay.com/photo/2015/07/15/06/14/gradient-845701\_960\_720.jpg") |
アフター
1 |
background: linear-gradient(135deg, #fbc6ff 20%, #bdfff9 90%); |
画像によるレイアウトシフトのCSSを改善
ブラウザは、画像が読み込まれて初めて画像のサイズを決定できます。ページがレンダリングされた後に画像の読み込みが行われた場合、画像用のスペースが確保されていないと、画像が表示されたときにレイアウトシフト(レイアウトのずれ)が発生します。サンプルページでは、ヒーロー画像が読み込まれるときにレイアウトシフトが発生します。
補足: レイアウトシフトを引き起こす画像の現象は、画像の読み込みが遅い状況でより明白になります。例えば、接続が遅い場合や、ファイルサイズが特に大きい画像を読み込む場合などです。
原因を特定する
widthとheightが明示されていない画像を識別するには、Lighthouseの「Image elements have explicit width and height」を使用します。
Lighthouseの「Image elements have explicit width and height」
この例では、ヒーロー画像と記事画像の両方にwidthとheightがありません。
修正方法
レイアウトシフトを避けるために、2つの画像にwidthとheightを設定します。
ビフォー
1 2 |
<img src="https://source.unsplash.com/random/2000x600" alt="image to load in"> <img src="https://source.unsplash.com/random/800x600" alt="image to load in"> |
アフター
1 2 |
<img src="https://source.unsplash.com/random/2000x600" width="2000" height="600" alt="image to load in"> <img src="https://source.unsplash.com/random/800x600" width="800" height="600" alt="image to load in"> |
修正すると、レイアウトシフトをせずに画像が読み込まれるようになりました。
画像用のスペースが確保されていないと、レイアウトシフト(レイアウトのずれ)が発生する
注: 画像を読み込む別のアプローチはwidthとheightを設定するとともに、srcsetとsizes属性を使用することです。この方法で、異なるデバイスに異なるサイズの画像を提供できるという、パフォーマンス上の利点があります。詳しくは、Serve responsive imagesをご覧ください。
WebフォントのCSSを改善
Webフォントは、テキストのレンダリングを遅らせたり、レイアウトシフトを引き起こす原因となります。そのため、フォントを迅速に提供することが重要となります。
テキストレンダリングの遅延
デフォルトでは、ブラウザは使用するWebフォントがまだ読み込まれていない場合、テキスト要素をすぐにはレンダリングしません。これは、「スタイルなしテキストの点滅(FOUT)」を防ぐためです。多くの場合、これはFirst Contentful Paint(FCP)を遅らせることになります。場合によっては、Largest Contentful Paint(LCP)も遅らせることになります。
補足: デフォルトでは、ChromiumベースとFirefoxのブラウザは関連するWebフォントが読み込まれていない場合、テキストのレンダリングを最大3秒間ブロックします。Safariは無期限にブロックします。ブロック期間は、ブラウザがWebフォントを要求したときに始まります。ブロック期間が終了してもまだフォントが読み込まれていない場合、ブラウザはフォールバックフォントを使ってテキストをレンダリングし、使用可能になるとWebフォントにスワップします。
Webフォントによるレイアウトシフト
フォントのスワップ(入れ替え)は、コンテンツをユーザーに素早く表示するのに優れていますが、レイアウトシフトを引き起こす可能性があります。レイアウトシフトは、Webフォントと予備フォントがページ上で異なるスペースを占めるときに発生します。似たような比率のフォントを使用することで、このようなレイアウトシフトを最小限に抑えることができます。
フォントのスワップ(入れ替え)により、ページ要素が5px上にシフトしました。
原因を特定する
特定のページで読み込まれているフォントを確認するには、デベロッパーツールの「Network」タブを開き、「Font」でフィルタリングします。フォントは大きなファイルになる可能性があるため、一般的には使用するフォントの数を少なくした方がパフォーマンスが向上します。
「Network」タブを開き、「Font」をクリック
フォントがリクエストされるまでの時間を確認するには、「Timing」タブをクリックします。フォントはリクエストされるのが早ければ早いほど、すぐに読み込んで使用することができます。
「Timing」タブをクリック
フォントのリクエストチェーンを見るには、「Initiator」タブをクリックします。一般的に、リクエストチェーンが短ければ短いほど、そのフォントをすぐにリクエストされます。
「Initiator」タブをクリック
修正方法
このサンプルページでは、Google Fonts APIを使用しています。Google Fontsでは、<link>タグや@import文でフォントを読み込むオプションがあります。 <link>のコードにはpreconnectリソースヒントが含まれており、これにより@importを使用した場合よりもスタイルシートの配信が速くなります。
リソースヒントとは、特定の接続を設定したり、特定のリソースをダウンロードしたりする必要があることをブラウザに示唆する方法です。その結果、ブラウザはこれらのアクションを優先的に実行します。リソースヒントを使用する際は、特定のアクションに優先順位を付けることで、他のアクションからブラウザのリソースが奪われることに注意してください。したがって、リソースヒントは慎重に使用する必要があります。詳しくは、Establish network connections early to improve perceived page speedをご覧ください。
スタイルシートから@importを削除します
1 |
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400&family=Roboto:wght@300&display=swap'); |
下記の<link>タグをドキュメントの<head>内に追加します。
1 2 |
<link rel="preconnect" href="https://fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" rel="stylesheet"> |
これらの<link>タグは、ブラウザにhttps://fonts.gstatic.comへの早期接続を確立し、MontserratとRobotoのフォント宣言を含むスタイルシートを読み込むように指示します。これらの<link>タグは、<head>内のできるだけ上に記述する必要があります。
補足: Google Fontsから一部の文字だけを使用する場合(サブセット)は、パラメータに「?text=」を追加します。例えば、?text=ABCと記述すると、「ABC 」を表示するのに必要な文字のみを読み込みます。これはフォントのファイルサイズを小さくするのに適した方法です。
アニメーションのCSSを改善
アニメーションがWeb Vitalsに影響を与える主な原因は、アニメーションがレイアウトシフトを引き起こす場合です。使用を避けるべきアニメーションには、レイアウトシフトを引き起こすアニメーションと、ページ要素を動かすアニメーションのようなエフェクトの2種類があります。通常、これらのアニメーションは、transform, opacity, filterなどのCSSプロパティを使用して、よりパフォーマンスの高い同等のものに置き換えることができます。詳しくは、How to create high-performance CSS animationsをご覧ください。
原因を特定する
Lighthouseの「Avoid non-composited animations」は、パフォーマンスの低いアニメーションを特定するのに役立つ場合があります。
Lighthouseの「Avoid non-composited animations」
注: Lighthouseの「Avoid non-composited animations」では、パフォーマンスの低いCSSアニメーションのみが特定されます。JavaScriptによるアニメーション(例えば、setInterval()を使用して要素をアニメーション化)はパフォーマンスに悪影響を及ぼしますが、この監査ではフラグが立てられません。
修正方法
slideInのアニメーションシーケンスを、margin-leftプロパティのトランジションではなく、transform: translateX()を使用するように変更します。
ビフォー
1 2 3 4 5 6 7 8 9 10 11 12 |
.header { animation: slideIn 1s 1 ease; } @keyframes slideIn { from { margin-left: -100%; } to { margin-left: 0; } } |
アフター
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.header { animation: slideIn 1s 1 ease; } @keyframes slideIn { from { transform: translateX(-100%); } to { transform: translateX(0); } } |
クリティカルCSS
スタイルシートはレンダリングをブロックします。ブラウザが読み込む際にスタイルシートに遭遇し、ブラウザがスタイルシートをダウンロードして解析するまで、他のリソースのダウンロードを停止します。
これにより、LCPが遅延する可能性があります。パフォーマンスを向上させるためには、未使用のCSSを削除し、重要なCSSをインライン化し、重要でないCSSを延期することを検討してください。
参考: Webページの表示が早くなる!既存ページのクリティカル レンダリング パスを最適化するオンラインツール
終わりに
まだまだ改善の余地はありますが(例えば、画像圧縮を利用して画像をより早く配信するなど)、ここで解説した修正により、このサンプルページのWeb Vitalsは大幅に改善されました。これが実際のサイトであれば、次のステップとして、実際のユーザーからパフォーマンスデータを収集し、ユーザーにとってWeb Vitalsのしきい値を満たしているかどうかを評価する必要があります。Web Vitalsの詳細については、Learn Web Vitalsをご覧ください。
sponsors