CLSのガタつきを画像の寸法指定と広告枠の予約で止める手順
記事を開いて読み始めた。その瞬間、上に画像が差し込まれて、読んでいた行が画面の下へ逃げる。押そうとしたリンクの位置に、別のボタンが滑り込んでくる。——このガタつきを数値にしたのが CLS(Cumulative Layout Shift:表示中に要素が予期せずずれる度合い)です。
答えを先に書きます。直す作業の大半は「読み込みが終わる前に、場所を先に確保する」ことです。画像と動画には width と height の属性を書く。広告や埋め込みのように中身の大きさが分からない枠には、CSS で高さの下限を与える。どこを直すかは、Chrome の開発者ツールで「ずれた要素」を特定してから決めます。
なぜ寸法がないとずれるのか
ブラウザは、画像が届くまでその大きさを知りません。
大きさが分からない画像には、最初は高さのない場所しか用意されません。画像が届いた瞬間に高さが決まり、その下にある本文が押し下げられます。これがずれの正体です。
web.dev の最適化ガイドは、CLS が悪化するよくある原因として次の4つを挙げています。
- 寸法の指定がない画像
- 寸法の指定がない広告・埋め込み・iframe
- 寸法の指定がないまま、あとから差し込まれる広告・埋め込み・iframe
- ウェブフォント
上の3つは、どれも「寸法がない」ことが共通しています。逆に言えば、寸法を先に伝えれば、ブラウザは画像の到着を待たずに正しい大きさの場所を空けておけます。同ガイドも、画像と動画の要素には width と height の属性を必ず付けるか、CSS の aspect-ratio(縦横比)などで必要な場所を確保するよう勧めています。そうすれば、画像の読み込み中でも文書の中に正しい大きさの場所を割り当てられる、という説明です。
目安の数値と、検索との関係
web.dev の CLS 解説では、良好な体験のために CLS を 0.1以下に保つことが目安とされています。0.25を超えると「不良」です。判定は、モバイルとパソコンを分けたうえで、ページ表示の75パーセンタイル(値の小さい順に並べて75%目にあたる値)で見ることが勧められています。手元で1回開いてずれなかったから大丈夫、とはなりません。
| CLS の値 | 判定 |
|---|---|
| 0.1以下 | 良好 |
| 0.1を超え、0.25以下 | 良好と不良の間(目安を満たしていない) |
| 0.25を超える | 不良 |
Google 検索セントラルも、主要な指標として「CLS が0.1未満」を挙げ、良好なコアウェブバイタルはほかのページ体験の要素とあわせて、Google のコアランキングシステムが評価しようとするものと一致している、と説明しています。ただし、これは「CLS を直せば順位が上がる」という約束ではありません。まずは読者が読みづらさを感じている問題として扱うのが筋です。
もう1つ押さえておきたいのは、CLS がページを開いている間ずっと測られることです。web.dev は、CLS がページの全期間を対象にするため、タブが数日から数か月開かれたままになる場合もある、と注意しています。読み込み直後だけ確認して終わると、スクロールした先で起きるずれを見落とします。
ずれた要素を特定して直す7ステップ
ここからが作業手順です。ステップ1〜3で「何がずれたか」、4〜6で「どう場所を確保するか」、7で「直ったか」を確かめます。
- 対象のページを決める。Search Console のウェブに関する主な指標レポートや PageSpeed Insights で、CLS が良好の目安を満たしていないと表示されているページを1つ選びます。レポートの見方や、どの指標が悪いのかの切り分けはコアウェブバイタル悪化を切り分ける5つの手順で整理しています。
- 読み込みを記録する。Chrome で対象ページを開き、開発者ツール(DevTools)の「パフォーマンス」パネルで「記録して再読み込み(Record and reload)」を押します。Chrome の公式リファレンスによると、DevTools はいったん空白ページに移って前の記録を消し、再読み込み中の動きを記録して、読み込み完了の数秒後に自動で止めます。手元の PC が速すぎてずれが出にくいときは、記録の設定で CPU の速度を落とします。リファレンスでは、低〜中価格帯のスマートフォンに近づけるための調整方法も案内されています。
- ずれた要素を見つける。結果の「Layout shifts」のトラックに、紫のひし形が並びます。ひし形1つが1回のずれで、時間的に近いものは紫の線でまとまり(クラスタ)として表示されます。ひし形にマウスを重ねると、ずれの原因になった要素が画面上で強調されます。クリックすると、下の「概要(Summary)」タブに、時刻・スコア・ずれた要素・原因の候補が出ます。
- 要素を3種類に仕分ける。見つかった要素が「寸法の分かっている画像・動画」なのか、「大きさが配信のたびに変わる広告枠」なのか、「中身の大きさが読み込むまで分からない埋め込み」なのかを分けます。直し方がそれぞれ違うためです(下の表)。
- 画像と動画に width と height を書く。元画像の幅と高さを、HTML の属性にそのまま書きます。表示サイズは CSS で調整します。
- 広告枠と埋め込みに場所を確保する。外側の入れ物(コンテナ)に min-height(高さの下限)や aspect-ratio を指定します。どの高さを選ぶかは次の節で扱います。
- もう一度記録して比べる。ステップ2と同じ条件で記録し、紫のひし形が減ったか、同じ要素が出てこなくなったかを確かめます。現場のデータ(実際の利用者の記録)に反映されるまでには時間がかかるため、まずはこの手元の記録で効果を確認します。
要素ごとの場所の確保のしかた
ステップ4で仕分けた要素は、次の表のように扱います。
| 要素の種類 | 大きさは事前に分かるか | 場所の確保のしかた | つまずき所 |
|---|---|---|---|
| 画像・動画 | 分かる(元の寸法がある) | <img> <video> に width と height 属性を書き、CSS で width: 100%; height: auto; | 属性を書いても CSS で高さを固定値にすると縦横比が崩れる |
| レスポンシブ画像(srcset) | 候補の縦横比が同じなら分かる | 候補画像の縦横比をそろえ、代表の寸法を width と height に書く | 縦横比の違う画像を srcset に混ぜると、1組の寸法では表せない |
| 広告枠 | 配信ごとに変わる | 外側のコンテナに min-height を指定する | 最大サイズで確保すると空白が増える |
| 埋め込み(SNS 投稿・地図など) | 読み込むまで分からないことが多い | コンテナに min-height や aspect-ratio を指定する | 提供元が場所を確保してくれるとは限らない |
画像:属性を書くだけで縦横比が伝わる
「レスポンシブにしたいから、width と height は書かないほうがいい」と考える人がいます。これは逆です。
web.dev のガイドによると、Chrome では属性を書いた画像に対して、開発者ツールの「スタイル」欄に aspect-ratio: auto 640 / 360 のような値が、HTML の属性から生まれたスタイルとして表示されます。Safari も同様で、Firefox はこの値を表示しないものの、レイアウトには使っています。つまり、ブラウザは属性の数値を「大きさの固定」ではなく「縦横比」として使い、場所を確保しています。
あとは CSS で表示幅を決めます。同ガイドは、コンテナの幅に合わせて画像を縮める例として、次の指定を示しています。
img {
width: 100%;
height: auto;
}
height: auto が肝心です。高さを固定値にしないことで、幅に合わせて高さが縦横比どおりに決まります。元画像より大きく引き伸ばしたくない場合は、width: 100% の代わりに max-width: 100% を使う書き方もあります。
srcset で複数の解像度を出し分ける場合、web.dev は「width と height を設定できるように、各画像の縦横比をそろえる」ことを条件にしています。
<img
width="1000"
height="1000"
src="eyecatch-1000.jpg"
srcset="eyecatch-1000.jpg 1000w, eyecatch-2000.jpg 2000w"
alt="記事のアイキャッチ画像"
/>
広告枠:どの高さで確保するか
広告は、ずれの大きな原因です。web.dev のガイドは、広告をウェブ上のずれの最大の原因の1つとし、広告や埋め込み、iframe などあとから差し込まれる中身が、その下のコンテンツを押し下げて CLS を悪化させると説明しています。
難しいのは、配信される広告の大きさが毎回変わることです。同ガイドは選択肢を3つ挙げています。
- 大きめのコンテナを用意して、小さい広告が来てもずれないようにする
- 過去の配信実績から、最も出やすい大きさで枠を確保する
- 使われる最小の大きさを初期値にし、大きい広告のときは多少のずれを受け入れる
前の2つは、ずれを抑える代わりに、ページ上の空白が増えます。3つめは min-height を使う方法で、空の要素の初期値である高さ0と比べれば、ずれの影響を小さくしつつ、必要に応じてコンテナが伸びます。
どれを選ぶかは、空白とずれのどちらを許せるかで決まります。本文の途中に置く枠なら、空白が大きいと読む流れが途切れます。その場合は、配信実績で最も多い大きさに合わせるのが現実的なことが多いはずです。
.ad-slot {
min-height: 250px; /* 配信実績で最も多い広告の高さに合わせる */
}
埋め込み:提供元任せにしない
SNS の投稿や動画、地図の埋め込みは、読み込む前に自分の中身の大きさを知らないことが多い、と web.dev は説明しています。そのため提供元が場所を確保しないことがあり、読み込み終わった時点でずれが起きます。
自社のテンプレートで、埋め込みを包むコンテナに場所を確保しておくのが確実です。動画のように縦横比が決まっているものは aspect-ratio、SNS 投稿のように高さが読めないものは min-height が向いています。
.embed-video {
aspect-ratio: 16 / 9;
}
.embed-post {
min-height: 400px;
}
例:ブログ記事ページで7ステップを通す
ここで、よくある構成のブログ記事ページに当てはめてみます。ページの上から順に、見出し、アイキャッチ画像、本文、本文の途中に広告枠、記事末尾に SNS 投稿の埋め込み、という構成だとします。
ステップ2で「記録して再読み込み」を押し、ステップ3で紫のひし形を見ると、読み込みの序盤にまとまりが2つ出たとします。
1つめのひし形にマウスを重ねると、本文全体が強調された。概要タブで原因の候補を見ると、アイキャッチ画像が挙がっている。HTML を確認すると、<img src="eyecatch.jpg" alt="..."> だけで width と height がない。これが表の1行目、「画像・動画」のケースです。元画像の寸法(たとえば幅1200、高さ630)を属性に書き、CSS は height: auto に直します。
2つめのひし形は、本文の後半が強調された。原因の候補は広告枠の直後の段落です。広告タグが読み込まれてから枠が広がり、下の段落を押し下げていました。表の3行目です。配信実績で最も多い広告の高さを min-height にして、枠を先に確保します。
記事末尾の SNS 埋め込みは、読み込み直後の記録には出てきませんでした。ただ、表示位置がページの下のほうなので、スクロールしたときにずれている可能性があります。ここは表の4行目として、コンテナに min-height を先に入れておきます。
ステップ7で再記録し、2つのまとまりが消えたかを確認します。消えていれば、手元での修正は完了です。
よくある誤解:「すべての動きが減点される」わけではない
ずれを嫌うあまり、アコーディオンやタブの開閉までなくそうとする必要はありません。
web.dev の CLS 解説は、すべてのレイアウトのずれが悪いわけではないとしています。悪いのは、利用者が予期していないずれです。利用者の操作から500ミリ秒以内に起きたずれは、計算から除外できるよう印が付きます。この印が付くのは、タップやクリックのような区切りのある操作に限られます。
そのため、「もっと見る」を押して中身が開く動きは、多くの場合問題になりません。注意したいのは、押したあとに通信を待ってから中身が差し込まれるような作りです。待ち時間が長いと、操作から500ミリ秒を超えてずれが起き、除外の対象から外れることがあります。押した直後に枠だけ先に広げておくと安全です。
もう1つ、読み込み後のずれは手元の記録に出にくい点にも注意が必要です。web.dev は、実際の利用者のデータ(CrUX)と Lighthouse の CLS が食い違うときは、読み込み後に起きたずれが原因であることが多いと説明しています。Search Console では悪いのに手元の記録ではずれが見えない。そんなときは、スクロールや操作をしながら記録して、遅れて差し込まれる要素を探します。
自分のページで確かめるチェックリスト
最後に、テンプレートを点検するときの確認項目をまとめます。
| 確認項目 | 見る場所 | 問題があるときの直し方 |
|---|---|---|
すべての <img> <video> に width と height があるか | HTML のテンプレート | 元画像の寸法を属性に書く |
| 画像の CSS で高さを固定値にしていないか | CSS | height: auto に変える |
| srcset の候補画像の縦横比がそろっているか | 画像の書き出し設定 | 同じ縦横比で書き出し直す |
| 広告枠のコンテナに min-height があるか | 広告タグを包む要素 | 配信実績で最も多い高さを指定する |
| 埋め込みのコンテナに場所が確保されているか | 埋め込みを包む要素 | aspect-ratio か min-height を指定する |
| 遅延読み込みの画像にも寸法があるか | loading="lazy" の付いた画像 | 遅延読み込みでも属性は書く |
最後の項目は見落とされがちです。遅延読み込みは画像が届くタイミングを遅らせるだけで、寸法の問題は残ります。画面の下のほうの画像ほど、スクロールした先でずれを起こしやすくなります。遅延読み込みの使いどころは画像の遅延読み込みは検索に不利?公式が見る2つの条件で扱っています。
CLS が片づいたら、次は操作したときの反応の遅さも見ておくと、ページ体験の指標を一通り点検できます。手順はINPが「改善が必要」なときに遅い操作を特定して直す手順にまとめています。
出典
