レイアウトの急激な変化を避け、ユーザー エクスペリエンスを向上させる方法を学びます
Cumulative Layout Shift(CLS)は、Core Web Vitals の 3 つの指標のうちの 1 つです。ビューポート内での表示コンテンツの移動量と、影響を受ける要素の移動距離を組み合わせて、コンテンツの不安定性を測定します。
レイアウト シフトはユーザーの注意をそらす可能性があります。ある記事を読み始めたところで、ページの周りの要素が突然移り変わり、目が離され、もう一度自分の場所を見つける必要が出てくるかもしれません。これは、ニュースを読んでいるときや、[検索] をクリックしようとするときなど、ウェブ上でよく見られます。または [カートに追加]できます。このようなエクスペリエンスは、見た目が不快でストレスを感じるものです。この問題は、別の要素が突然ページに追加されたりサイズ変更されたりして、可視要素が強制的に移動された場合に発生します。
優れたユーザー エクスペリエンスを提供するには、ページアクセスの 75% 以上で CLS を 0.1 以下にするよう努める必要があります。
<ph type="x-smartling-placeholder">秒単位またはミリ秒単位で測定される時間ベースの値である他の Core Web Vitals とは異なり、CLS スコアは、コンテンツの量と移動量の計算に基づく単位のない値です。
このガイドでは、レイアウト シフトの一般的な原因の最適化について説明します。
CLS が低い一般的な原因は次のとおりです。
- サイズのない画像。
- ディメンションなしの広告、埋め込み、iframe。
- 広告、埋め込み、iframe など、動的に挿入されるコンテンツ(ディメンションなし)。
- ウェブフォント。
レイアウト シフトの原因を理解する
CLS の一般的な問題の解決策を検討する前に、CLS スコアと、変化の原因を把握することが重要です。
ラボツールの CLS とフィールドの CLS の比較
Chrome UX レポート(CrUX)で測定された CLS は、Chrome DevTools や他のラボツールで測定した CLS と一致しないため、デベロッパーが誤った認識を持つことがよくあります。Lighthouse などのウェブ パフォーマンス ラボのツールは通常、ページを読み込むだけでウェブ パフォーマンス指標を測定し、ガイダンスを提供するため、ページの完全な CLS が表示されないことがあります(ただし、Lighthouse のユーザーフローでは、デフォルトのページ読み込みの監査を超えて測定できます)。
CrUX は、Web Vitals プログラムの公式データセットです。そのため、CLS は、ラボツールで通常測定される最初のページ読み込み時だけでなく、ページ全体を通じて測定されます。
レイアウト シフトは、最初にページをレンダリングするために必要なリソースがすべて取得されるため、ページの読み込み中によく発生しますが、初期読み込みの後にも発生することがあります。読み込み後のシフトの多くは、ユーザー インタラクションの結果として発生する可能性があります。そのため、そのインタラクションから 500 ミリ秒以内に発生する場合は、「想定」のシフトであるため、CLS スコアから除外されます。
ただし、適格なインタラクションがなければ、ユーザーが予期しないその他の読み込み後の移動(たとえば、ページに沿ってさらにスクロールすると、遅延読み込みコンテンツが読み込まれて移動が発生する)が含まれる場合があります。読み込み後の CLS のその他の一般的な原因は、遷移のインタラクションです。たとえば、シングルページ アプリの場合は、500 ミリ秒の猶予期間よりも長くかかります。
PageSpeed Insights では、ユーザーが認識した 「実際のユーザーが経験していることを知る」の URL から CLS を取得セクション 「Diagnose performance issues」にあるラボベースの読み込み CLS です。。 これらの値の相違は、読み込み後の CLS の結果である可能性があります。
<ph type="x-smartling-placeholder"> <ph type="x-smartling-placeholder">読み込み CLS の問題を特定する
PageSpeed Insights の CrUX スコアと Lighthouse CLS スコアがおおむね一致している場合、通常は Lighthouse で検出された負荷 CLS の問題があることを示しています。この場合、Lighthouse では 2 つの監査が行われ、幅と高さがないために CLS の原因となる画像に関する詳細情報が提供されます。また、ページの読み込み時にシフトしたすべての要素と、その CLS の寄与度が一覧表示されます。CLS 監査でフィルタすると、これらの監査を表示できます。
<ph type="x-smartling-placeholder"> <ph type="x-smartling-placeholder">DevTools の [Performance] パネルでも、[Experience] セクションでレイアウト シフトがハイライト表示されます。Layout Shift
レコードの [Summary] ビューには、レイアウト シフトの累積スコアと、影響を受けるリージョンを示す長方形のオーバーレイが含まれます。これは、読み込み CLS の問題に関する詳細情報を取得する場合に特に役立ちます。これは、再読み込みパフォーマンス プロファイルで簡単に再現できるためです。
読み込み後の CLS の問題を特定する
CrUX と Lighthouse の CLS スコアが一致しない場合は、多くの場合、読み込み後の CLS を示している。このような変化は、フィールド データなしでは追跡が難しい場合があります。フィールド データの収集について詳しくは、フィールドの CLS 要素を測定するをご覧ください。
Chrome 拡張機能「Web Vitals」を使用すると、ヘッドアップ ディスプレイやコンソールでページを操作する際に CLS をモニタリングできます。コンソールでは、シフトした要素の上に詳細情報が表示されます。
この拡張機能を使用する代わりに、コンソールに貼り付けた Performance Observer を使用してレイアウト シフトを記録しながら、ウェブページを閲覧することもできます。
シフトのモニタリングを設定したら、読み込み後の CLS の問題を再現できます。CLS は多くの場合、ユーザーがページをスクロールしているとき、つまり遅延読み込みコンテンツが完全に読み込まれ、それに対応するスペースが確保されていないときに発生します。ユーザーがポインタを合わせたときにコンテンツがシフトすることは、読み込み後の CLS の一般的な原因の一つです。これらのインタラクション中にコンテンツのシフトがあった場合、たとえ 500 ミリ秒以内に発生したとしても、想定外と見なされます。
詳細については、レイアウト シフトをデバッグするをご覧ください。
CLS の一般的な原因を特定したら、Lighthouse のタイムスパン ユーザーフロー モードを使用して、レイアウト シフトによって一般的なユーザーフローが回帰しないようにすることもできます。
フィールドの CLS 要素を測定する
現場で CLS をモニタリングすることは、CLS がどのような状況で発生するかを特定し、考えられる原因を絞り込むうえで非常に役立ちます。ほとんどのラボツールと同様に、フィールド ツールは変化した要素のみを測定しますが、通常はそれによって原因を特定できるだけの十分な情報が得られます。また、CLS フィールド測定値を使用して、修正の優先順位が最も高い問題を特定することもできます。
web-vitals
ライブラリのアトリビューション関数を使用すると、この追加情報を収集できます。詳しくは、フィールドでパフォーマンスをデバッグするをご覧ください。他の RUM プロバイダも、同様の方法でこのデータの収集と表示を開始しています。
CLS の一般的な原因
CLS の原因を特定したら、問題の修正を開始できます。このセクションでは、CLS のより一般的な理由と、回避するための方法について説明します。
サイズのない画像
画像要素と動画要素には、width
と height
のサイズ属性を必ず含めてください。または、CSS aspect-ratio
などを使用して必要なスペースを予約します。この方法により、画像の読み込み中にブラウザがドキュメント内の適切なスペースを割り振ることができます。
画像の width
属性と height
属性の履歴
ウェブの初期段階では、デベロッパーは width
属性と height
属性を <img>
タグに追加して、ブラウザが画像の取得を開始する前にページに十分なスペースが割り当てられるようにします。これにより、リフローと再レイアウトを最小限に抑えることができます。
<img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons">
この例の width
と height
には単位が含まれていません。この「ピクセル」はブラウザがページのレイアウト内に 640×360 の領域を予約するように設定できます。実際のサイズが一致するかどうかにかかわらず、このスペースに合わせて画像が引き伸ばされます。
レスポンシブ ウェブ デザインが導入されたとき、デベロッパーは width
と height
を省略し、代わりに CSS を使用して画像のサイズを変更するようになりました。
img {
width: 100%; /* or max-width: 100%; */
height: auto;
}
ただし、画像サイズが指定されていないため、ブラウザが画像のダウンロードを開始してサイズを決定できるようになるまで、容量を割り当てることはできません。画像の読み込みに伴い、スペースを確保するためにテキストがページを下方に移動するため、ユーザー エクスペリエンスは混乱し、ストレスを感じることになります。
そこで重要な役割を果たすのがアスペクト比です。画像のアスペクト比とは、画像の幅と高さの比率です。これは、コロンで区切られた 2 つの数値として表されるのが一般的です(例: 16:9、4:3)。x:y アスペクト比の場合、画像は幅が x 単位、高さが y 単位です。
つまり、ディメンションの 1 つがわかっていれば、もう 1 つのディメンションを決定できます。アスペクト比 16:9 の場合:
- puppy.jpg の高さが 360 ピクセルの場合、幅は 360 x (16 / 9) = 640 ピクセル
- puppy.jpg の幅が 640 ピクセルの場合、高さは 640 x (9 / 16) = 360 ピクセル
画像のアスペクト比がわかれば、ブラウザは高さと関連する領域を考慮して十分なスペースを計算して確保できます。
画像のサイズ設定に関する最新のベスト プラクティス
最新のブラウザでは、画像のデフォルトのアスペクト比は
画像の width
属性と height
属性を使用すると、レイアウト シフトを防止できます。
これらの属性を画像に設定し、前の CSS を
あります。
<!-- set a 640:360 i.e a 16:9 aspect ratio -->
<img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons">
すべてのブラウザでは、要素の既存の width
属性と height
属性に基づいてデフォルトのアスペクト比が追加されます。
これにより、画像の読み込み前の width
属性と height
属性に基づいてアスペクト比が計算されます。この情報は、レイアウト計算の開始時に提供されます。画像の幅(width: 100%
など)が指示されると、すぐにアスペクト比を使用して高さが計算されます。
この aspect-ratio
値は、デフォルトのユーザー エージェント スタイルシートではなく、HTML の処理時に主要なブラウザで計算されるため(その理由についてはこちらの投稿をご覧ください)、値の表示が若干異なります。たとえば、[要素] パネルの [スタイル] セクションには、次のように表示されます。
img[Attributes Style] {
aspect-ratio: auto 640 / 360;
}
Safari でも、HTML 属性スタイルソースを使用した場合も同様に動作します。Firefox では、この計算された aspect-ratio
が [Inspector] パネルには一切表示されませんが、レイアウトに使用されます。
上記のコードの auto
部分は重要です。これは、画像のダウンロード後に画像のサイズによってデフォルトのアスペクト比がオーバーライドされるためです。画像のサイズが異なる場合でも、画像の読み込み後にレイアウトがシフトしますが、HTML が正しくない場合に備えて、画像のアスペクト比が利用可能になると、引き続きそのアスペクト比が使用されます。実際のアスペクト比がデフォルトと異なっていても、サイズが指定されていない画像でデフォルト サイズ 0x0 の場合よりもレイアウト シフトが少なくなります。
アスペクト比の詳細やレスポンシブな画像については、メディアのアスペクト比を使用したジャンクのないページ読み込みをご覧ください。
画像がコンテナ内にある場合は、CSS を使用して、コンテナの幅に合わせて画像のサイズを変更できます。画像の高さに固定値が使用されないように、height: auto;
を設定します。
img {
height: auto;
width: 100%;
}
レスポンシブな画像についてはどうでしょうか。
レスポンシブ画像を使用する場合は、srcset
でブラウザが選択できる画像と各画像のサイズを定義します。<img>
の幅と高さの属性を設定できるようにするには、各画像で同じアスペクト比を使用する必要があります。
<img
width="1000"
height="1000"
src="puppy-1000.jpg"
srcset="puppy-1000.jpg 1000w, puppy-2000.jpg 2000w, puppy-3000.jpg 3000w"
alt="Puppy with balloons"
/>
お客様の画像アスペクト比は アート ディレクション。 たとえば、縦長のカメラには、画像の切り抜かれたショットを含めて、 デスクトップに画像全体を表示するという方法もあります。
<picture>
<source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" />
<source media="(min-width: 800px)" srcset="puppy-800w.jpg" />
<img src="puppy-800w.jpg" alt="Puppy with balloons" />
</picture>
Chrome、Firefox、Safari で width
と height
の設定がサポートされるようになりました
特定の <picture>
要素内の <source>
要素:
<picture>
<source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" width="480" height="400" />
<source media="(min-width: 800px)" srcset="puppy-800w.jpg" width="800" height="400" />
<img src="puppy-800w.jpg" alt="Puppy with balloons" width="800" height="400" />
</picture>
広告、埋め込み、その他の遅延読み込みコンテンツ
レイアウト シフトを引き起こす可能性があるコンテンツは画像だけではありません。広告、埋め込み、iframe、その他の動的に挿入されるコンテンツはすべて、その後に表示されるコンテンツのシフトダウンの原因となり、CLS を増加させる可能性があります。
広告は、ウェブ上のレイアウト シフトに大きく貢献しています。多くの場合、広告ネットワークやパブリッシャーは動的な広告サイズに対応しています。広告サイズを使用すると、クリック率が向上し、オークションに参加する広告が増えるため、パフォーマンスや収益の向上につながります。表示中のコンテンツが広告とともに押し下げられるため、ユーザー エクスペリエンスが低下する可能性があります。
埋め込み可能なウィジェットを使用すると、YouTube の動画、Google マップの地図、ソーシャル メディアの投稿など、ポータブルなウェブ コンテンツをページに追加できます。しかし、こうしたウィジェットは多くの場合、読み込み前に内容のサイズを認識していません。そのため、埋め込みを提供するプラットフォームではウィジェットのスペースが常に確保されているとは限らず、最終的に読み込まれたときにレイアウト シフトが発生します。
これらに対処するための手法はすべて似ています。主な違いは、挿入されるコンテンツをどの程度制御できるかです。これが広告パートナーなどの第三者によって挿入された場合、挿入されるコンテンツの正確なサイズがわからない場合があります。また、埋め込み内で発生するレイアウト シフトを制御することもできません。
コンテンツの遅延読み込み用にスペースを確保する
遅延読み込みコンテンツをコンテンツ フローに配置する場合は、初期レイアウトにそのコンテンツ用のスペースを確保することで、レイアウト シフトを回避できます。
1 つの方法として、min-height
CSS ルールを追加してスペースを確保できます。また、広告などのレスポンシブ コンテンツの場合は、ブラウザがサイズが指定されている画像に自動的にこれを使用するのと同様に、CSS プロパティ aspect-ratio
を使用します。
メディアクエリを使用して、フォーム ファクタ間で広告やプレースホルダのサイズの微妙な違いを考慮する必要がある場合があります。
高さが固定されていないコンテンツ(広告など)では、レイアウト シフトを完全に排除するために必要なスペースの正確な量を確保できない場合があります。小さい広告が配信される場合は、レイアウト シフトを避けるため、大きいコンテナのスタイルを設定するか、過去のデータに基づいて広告スロットに最も適したサイズを選択します。この方法の欠点は、ページの空白スペースが増えることです。
代わりに、使用される最小サイズに初期サイズを設定し、より大きなコンテンツの場合はある程度のシフトを受け入れることもできます。前述のように、min-height
を使用すると、空の要素のデフォルト サイズ 0 ピクセルと比較して、レイアウト シフトの影響を抑えながら、必要に応じて親要素を拡大できます。
広告が返されない場合などに、プレースホルダを表示して予約済みスペースが折りたたまれないようにしてください。要素のために確保しておいたスペースを削除すると、コンテンツの挿入と同じくらい CLS が発生する可能性があります。
遅延読み込みされるコンテンツをビューポートの下部に配置する
動的に挿入されるコンテンツがビューポートの最上部に近い場合、通常は、ビューポートの下部に挿入されたコンテンツよりもレイアウト シフトが大きくなります。ただし、ビューポートの任意の場所にコンテンツを挿入すると、移動が発生します。挿入されたコンテンツ用のスペースを確保できない場合は、ページの後半に配置して CLS への影響を軽減することをおすすめします。
ユーザーの操作なしで新しいコンテンツを挿入しない
サイトを読み込もうとしたときにビューポートの上部または下部にポップインする UI が原因で、レイアウト シフトが発生した経験があるのではないでしょうか。広告と同様に、これは多くの場合、ページの残りのコンテンツを移動するバナーやフォームで発生します。
<ph type="x-smartling-placeholder">このようなタイプの UI アフォーダンスを表示する必要がある場合は、読み込み時にページのコンテンツが予期せず移動しないように、ビューポートに十分なスペースを事前に確保しておきます(プレースホルダ UI やスケルトン UI を使用するなど)。または、適切なコンテンツをオーバーレイすることで、要素がドキュメント フローの一部にならないようにします。このようなコンポーネントに関する推奨事項については、Cookie の通知に関するベスト プラクティスの投稿をご覧ください。
場合によっては、コンテンツを動的に追加することが、ユーザー エクスペリエンスの重要な要素となります。たとえば、アイテムのリストにより多くの商品を読み込む場合や、ライブフィードのコンテンツを更新する場合などです。このような場合に予期しないレイアウト シフトを回避するには、いくつかの方法があります。
- 固定サイズのコンテナ内で古いコンテンツを新しいコンテンツに置き換えるか、カルーセルを使用して移行後に古いコンテンツを削除します。移行が完了するまでは、リンクやコントロールをすべて無効にしてください。これにより、新しいコンテンツが導入される際に誤ってクリックやタップが発生してしまうことを回避できます。
- [さらに読み込む] ボタンや [更新] ボタンなどを使用して、ユーザーが新しいコンテンツの読み込みを開始できるようにします。コンテンツがすぐに表示されるように、ユーザーが操作を行う前にコンテンツをプリフェッチすることをおすすめします。ユーザー入力から 500 ミリ秒以内に発生するレイアウト シフトは、CLS にはカウントされません。
- コンテンツを画面外にシームレスに読み込み、表示が可能であることを知らせる通知をオーバーレイします(「上へスクロール」ボタンなど)。
アニメーション
CSS プロパティの値を変更すると、ブラウザがそれらの変更に対応することが必要になる場合があります。box-shadow
や box-sizing
などの一部の値は、再レイアウト、ペイント、コンポジットをトリガーします。top
プロパティと left
プロパティを変更すると、移動する要素が独自のレイヤにある場合でもレイアウト シフトが発生します。これらのプロパティを使用したアニメーション化は避けてください。
他の CSS プロパティは、再レイアウトをトリガーせずに変更できます。たとえば、transform
アニメーションを使用して、要素の移動、スケーリング、回転、傾斜などを行います。
translate
を使用して合成されたアニメーションは他の要素に影響を与えないため、CLS にはカウントされません。合成されていないアニメーションでも、再レイアウトは行われません。レイアウト シフトをトリガーする CSS プロパティについて詳しくは、高パフォーマンスのアニメーションをご覧ください。
ウェブフォント
ウェブフォントのダウンロードとレンダリングは通常、ウェブフォントのダウンロード前に次の 2 つの方法のいずれかで処理されます。
- 代替フォントがウェブフォントに置き換えられ、スタイルなしテキスト(FOUT)の Flash が発生します。
- 「非表示」ウェブフォントが利用可能になるまで、代替フォントを使用してテキストが表示されます(FOIT(非表示テキストの点滅))。
どちらの方法でもレイアウト シフトが発生する可能性があります。テキストが非表示の場合でも代替フォントでレイアウトされるため、ウェブフォントが読み込まれると、テキスト ブロックと周囲のコンテンツは、表示フォントの場合と同じように移動します。
テキストのシフトを最小限に抑えるには、次のツールが役立ちます。
font-display: optional
は、ウェブフォントが初期レイアウトの時点までで利用可能な場合にのみ使用されるため、再レイアウトを回避できます。- 適切な代替フォントが使用されていることを確認します。たとえば、
font-family: "Google Sans", sans-serif;
を使用すると、"Google Sans"
の読み込み中はブラウザのsans-serif
代替フォントが使用されます。font-family: "Google Sans"
のみを使用して代替フォントを指定しないと、デフォルトのフォントが使用されます(Chrome では「Times」です)。これは、デフォルトのsans-serif
フォントよりも適合しないセリフフォントです。 - フォント フォールバックの改善の投稿で詳しく説明されているとおり、新しい
size-adjust
、ascent-override
、descent-override
、line-gap-override
の API を使用して、フォールバック フォントとウェブフォントのサイズの差を最小限に抑えます。 - Font Loading API を使用すると、必要なフォントを取得するまでの時間を短縮できます。
<link rel=preload>
を使用して、重要なウェブフォントをできるだけ早く読み込みます。プリロードされたフォントは、First Paint を満たす可能性が高くなります。この場合、レイアウトは移動しません。
フォントに関するその他のベスト プラクティスについては、フォントに関するおすすめの方法をご覧ください。
ページが bfcache の対象となるようにして CLS を削減する
CLS スコアを低く抑えるために非常に効果的な方法は、ウェブページをバックフォワード キャッシュ(bfcache)の対象にすることです。
bfcache では、ページを離れた後、ページをブラウザのメモリに短時間保持するので、元のページに戻ったときに元のページが復元されます。つまり、前述したような理由で読み込み時に見られるような移動を発生させることなく、完全に読み込まれたページをすぐに利用できます。
この場合も、最初のページの読み込み時にレイアウト シフトが発生している可能性がありますが、ユーザーがページに戻ってきたときに同じレイアウト シフトが繰り返し表示されないということです。初期読み込み時であっても常にシフトを避けるようにする必要がありますが、完全に解決するのが難しい場合は、少なくとも bfcache ナビゲーションで移動しないようにすることで、影響を軽減できます。
「戻る」ナビゲーションと「次へ」ナビゲーションは多くのサイトで一般的です。たとえば、目次ページ、カテゴリページ、検索結果に戻るなどです。
この機能を Chrome に展開したところ、CLS が顕著に改善されました。
bfcache はすべてのブラウザでデフォルトで使用されますが、さまざまな理由により bfcache を使用できないサイトもあります。bfcache の使用を妨げる問題をテストして特定する方法の詳細については、bfcache ガイドをご覧ください。この機能を最大限に活用して、サイトの全体的な CLS スコアを向上させてください。
まとめ
このガイドで前述したように、CLS を特定して改善するためのさまざまな手法があります。Core Web Vitals には条件が組み込まれているため、CLS を完全に排除できない場合でも、これらの手法の一部を使用することで影響を軽減できるはずです。これによって制限内に収められ、ウェブサイトのユーザー エクスペリエンスの向上につながることが期待されます。