Cumulative Layout Shift (CLS) 問題の特定と修正

RUMデータ、Chrome DevTools、的確なCSSとHTMLの修正を活用して、すべてのCumulative Layout Shift問題を特定し解決する方法を学ぶ

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-27

Cumulative Layout Shift (CLS) 問題の特定と修正

このページは、Cumulative Layout Shift (CLS) シリーズの一部です。CLSは、予期しないコンテンツの移動を追跡することで、ページの視覚的な安定性を測定します。良好なCLSスコアは0.1未満であり、0.25を超えると不良とされます。CLSを初めて学ぶ場合は、計算式、しきい値、セッションウィンドウの仕組みについて、CLSハブページから始めてください。

CLSは、Core Web Vitalsの中で最もパフォーマンスが良い指標です。2025 Web Almanacによると、世界のウェブサイトの72%がCLSの基準をクリアしています。素晴らしい数字に聞こえますが、ほとんどの開発者が自分のマシンでCLSの問題に気付かないという事実があります。レイアウトシフトは、低速な回線を使用する初回の訪問者に対して発生し、キャッシュが効いた状態でDevToolsを確認する頃には、すべて正常に見えてしまいます。これこそが、CLSのデバッグを困難にしている原因です。

このガイドは、私がCLSのコンサルティングを行う際に使用している、正確なステップバイステップのプロセスに基づいています。まずCrUXとRUMデータを確認し、Chromeで検証してから、修正コードを記述します。

最終確認: Arjen Karel (2026年3月)

CLSのヒント: CLSは累計ではなく、セッションウィンドウで測定されます。ブラウザはレイアウトシフトをセッション(最大5秒、シフト間に1秒のギャップ)にグループ化し、CLSスコアは最悪のセッションになります。ページ読み込み中に一度でもシフトが集中すると、それ以外の訪問が完全に安定していても、CLSは不合格になる可能性があります。

ステップ1: Search ConsoleでCLSを確認する

何かを変更する前に、実際にCLSの問題があることを確認してください。Google Search Consoleにログインし、Core Web Vitalsに移動して、モバイルとデスクトップの両方を確認します。

Googleが「CLSの問題: 0.25超」または「CLSの問題: 0.1超」としてURLをフラグ付けしている場合、Chrome User Experience (CrUX) レポートから、実際のユーザーがサイトでレイアウトシフトを経験していることが確認できます。

生の計算能力とネットワーク速度が重要になるLCPやINPとは異なり、CLSの問題はデバイスや画面サイズに依存する可能性があります。同じような問題(サイズ未指定の画像、フォントの切り替え、挿入されたコンテンツ)がモバイルとデスクトップに影響を与える場合、画面サイズの違いにより、デスクトップの方がはるかに大きなCLS値を報告することがあります(表示されるビューポートの大部分が影響を受ける可能性があるため)。Search ConsoleはURLをグループ化するため、どのページタイプが影響を受けているかは分かりますが、どの要素がシフトしているかは分かりません。それにはRUMデータが必要です。

Core Web VitalsのCLS問題を示すGoogle Search Console。

ステップ2: RUMデータでCLS問題を特定する

Search Consoleは問題の存在を確認しますが、具体的な手掛かりはほとんど与えてくれません。どのページで、どのような条件で、どの要素がシフトしているかを見つける必要があります。そのためにはRUMツールが必要です。

私はまさにこれらの疑問に答えるためにCoreDashを構築しました。1つのscriptタグを追加するだけで、すべての実際の訪問者からCLSの要因データを収集し始めます。CLSデバッグのための重要なデータポイントはシフトしている要素、つまり実際に移動したDOMノードです。その情報がなければ、手探りでデバッグすることになります。

シフトしている要素を見つける

まず、要素ごとにグループ化されたCLSデータを確認します。CoreDashでは、CLSページに移動し、「要素別のCLS」でソートされたデータテーブルを表示します。これにより、すべての訪問者全体でどの要素が最もレイアウトシフトを引き起こしているかが分かります。最悪の要素をクリックして、その要素がシフトしたページのすべての指標をフィルタリングします。

シフトしている要素別に分類されたCLSスコアを示すCoreDash。

影響を受けているページを見つける

最も影響の大きいシフト要素でフィルタリングした後、URLの内訳を確認します。CLSの問題はサイト全体、またはテンプレート全体に及ぶ可能性があります。これで、CLSが特定のページタイプ(画像ギャラリーのある商品ページ、広告枠のあるブログ記事、ヒーローアニメーションのあるランディングページなど)に集中しているかどうかが分かります。どのページが失敗しているかを知ることで、どこに焦点を当てるべきかが明確になります。

新規訪問者とリピーターを比較する

これは私が実施するもう一つの簡単なチェックであり、多くの人が考えるよりも重要です。フォントの切り替えによるCLSは、フォントがキャッシュされていない場合にのみ発生します。width: autoによる画像のCLSは、画像がブラウザのキャッシュにない場合にのみ発生します。新規訪問者のCLSが大幅に悪い場合、キャッシュに依存するシフトが発生しており、キャッシュを無効にしない限り、開発者自身のマシンでそれを目にすることはありません(ヒント: 常にChromeのキャッシュを無効にしてください...しかし、それはまた別の機会に話しましょう)。

デバイスタイプとビューポートサイズを確認する

CLSは通常、LCPやINPとは異なるモバイル/デスクトップのパターンを示します。レスポンシブレイアウトは、特定のビューポートの幅や高さでのみ現れるシフトを引き起こす可能性があります。デスクトップで問題を引き起こした広告枠が、モバイルのビューポートには存在しないこともあります。ナビゲーションメニューが小さなブレイクポイントで異なるアニメーションをするかもしれません。デバイスタイプでCLSデータをグループ化して、どこで発生しているかを把握します。

ステップ3: ChromeでCLSをデバッグする

RUMデータから、どの要素がなぜシフトするのかが分かりました。次に、ローカルで問題を再現し、原因を突き止めます。

Core Web Vitals Visualizerを使用する

レイアウトシフトを確認する最も速い方法は、Core Web Vitals Visualizer Chrome拡張機能を使用することです。ページを読み込み、拡張機能のアイコンをクリックして再読み込みします。すべてのレイアウトシフトが色付きのオーバーレイでハイライトされ、何がどれだけ移動したかが正確に表示されます。視覚的な答えがすぐに得られるため、私はパフォーマンスパネルを開く前の最初のステップとしてこれを使用しています。

ページ上のレイアウトシフトをハイライト表示するCore Web Vitals Visualizer。

Chromeで条件を再現し、ネットワークスクリーンショットを確認する

ウォームキャッシュ状態では、CLSの問題は多くの場合目に見えません。DevToolsを開き、「Network」タブでキャッシュを無効にし、接続を「Slow 4G」にスロットリングします(これは私のお気に入りで、競合状態によって引き起こされるCLSを示してくれます)。次に、歯車アイコンをクリックし、(DevToolsが開いている間)キャッシュを無効にします。これにより、初回の訪問者が経験する条件をシミュレートします。ネットワークタブに移動し、スクリーンショットを有効にします。これでページを再読み込みし、シフトを観察します。

ChromeのPerformanceパネルを使用する

ほとんどのレイアウトシフトは、方法を知っていれば簡単に見つけることができますが、時には見逃してしまうこともあります。そんな時は、Chrome DevTools (Ctrl+Shift+I) を開き、詳細なデバッグのためにPerformanceパネルに移動します。Ctrl+Shift+Eを押して再読み込みし、記録します。ページが読み込まれた後、数回上下にスクロールします。記録を停止します。

「Layout Shifts」トラックを探します。各シフトは色付きのブロックとして表示されます。シフトをクリックすると以下が表示されます:

  • The shifting node: 移動したDOM要素
  • The shift score: 影響割合(impact fraction)と距離割合(distance fraction)を掛けたもの
  • hadRecentInput: シフトの前にユーザー入力があったかどうか(クリックやタップには500ミリ秒の猶予が与えられますが、スクロールにはありません

シフトがいつ発生するかに注目してください。ページ読み込み中のシフトは、サイズ未指定の画像、フォントの切り替え、またはCSSトランジションを示しています。スクロール中のシフトは、レイアウトプロパティを使用したスクロール連動アニメーションを示しています。

スクロール中のレイアウトシフトエントリを示すChromeのPerformanceパネル。

クイックテスト: すべてのトランジションを無効にする

レイアウトプロパティをアニメーション化するCSSトランジションは、読み込みフェーズ中にのみシフトし、再現が難しいため、厄介なCLSの原因となります。コンソールにこのスニペットを貼り付け、キャッシュを無効にしてページをハードリロードし、CLSを比較します:

document.head.insertAdjacentHTML('beforeend',
  '<style>*{transition-property:none!important}</style>');

トランジションを無効にした後にCLSが低下した場合、原因を特定したことになります。CSSトランジションデバッグガイドを使用して、原因となっている特定のトランジションを見つけます。

Layout Instability APIでCLSを測定する

Layout Instability APIを使用すると、JavaScriptで直接すべてのレイアウトシフトにアクセスできます。これはRUMツールが内部で使用しているのと同じAPIです:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      console.log('Layout shift:', {
        value: entry.value,
        sources: entry.sources?.map(s => ({
          node: s.node,
          previousRect: s.previousRect,
          currentRect: s.currentRect
        }))
      });
    }
  }
});
observer.observe({ type: 'layout-shift', buffered: true });

sources配列は、どの要素が移動したかを示します。hadRecentInputは、クリックやタップによる予期されるシフトを除外します。本番環境での測定には、CoreDashまたは他のRUMツールを使用してください。

ステップ4: CLS問題を修正する

どの要素がなぜシフトするのかが分かりました。次はそれらを修正します。CLSには、LCPのような連続したフェーズはありません。代わりに、レイアウトシフトには明確な原因のカテゴリがあります。以下は、私が監査中に遭遇する順に、最も一般的なものです。

1. 画像、動画、iframeの寸法が未指定

これはウェブ上でのCLSの最大の原因です。2025 Web Almanacによると、モバイルページの62%に少なくとも1つのサイズ未指定の画像があります。修正方法: <img><video>、および<iframe>タグには、常にwidthheight属性を含めます。

<img src="hero.jpg" width="800" height="450" alt="Description">

<style>
img {
    height: auto;
    max-width: 100%;
}
</style>

CSSのwidth: autoに注意してください。この単一の宣言はブラウザのアスペクト比計算を上書きし、HTMLで幅と高さを設定していてもレイアウトシフトを引き起こします。私はこれを数十のサイトで見てきました。開発者はマークアップで正しいことをすべて行いましたが、img { width: auto; height: auto; max-width: 100%; }のようなグローバルCSSルールがそれをすべて台無しにしました。完全な説明については、自動サイズ調整画像によるレイアウトシフトの修正を参照してください。画像とメディアのすべてのCLS原因(動画、iframe、アートディレクション、レスポンシブ画像、遅延読み込み、プレースホルダー)を網羅した完全なガイドについては、画像とメディアがレイアウトシフトを引き起こす仕組みを参照してください。

2. ウェブフォントの切り替え

ウェブフォントが読み込まれ、フォールバックフォントを置き換える際、サイズの違いがレイアウトシフトを引き起こします。2025 Web Almanacによると、ウェブフォントをプリロードしているページはわずか11%です。つまり、大多数のサイトがフォント切り替えによるCLSの脆弱性を抱えています。

修正には2つのステップがあります。まず、メトリクスの上書きを使用して、フォールバックフォントをウェブフォントの寸法に合わせます:

<style>
@font-face {
    font-family: 'My Font Fallback';
    src: local('Arial');
    size-adjust: 105.2%;
    ascent-override: 93%;
    descent-override: 24%;
    line-gap-override: 0%;
}

@font-face {
    font-family: 'My Font';
    src: url('/fonts/myfont.woff2') format('woff2');
    font-display: swap;
}

body {
    font-family: 'My Font', 'My Font Fallback', sans-serif;
}
</style>

Fallback Font Generatorを使用して、フォントのペアリングに対する正しい上書き値を計算します。次に、配信を高速化します: フォントをセルフホストし、重要なフォントファイルをプリロードし、サブセット化されたWOFF2を使用します。完全な戦略については、レスポンシブウェブフォントの読み込みウェブフォントの読み込み中にテキストを表示し続けるを参照してください。

3. CSSアニメーションとトランジション

2025 Web Almanacによると、モバイルページの40%が非合成(non-composited)アニメーションを実行しています。これらはwidthheighttopleftmarginpaddingなどのプロパティをアニメーション化し、すべてのフレームでレイアウトの再計算をトリガーします。

最も一般的な原因はtransition: allです。開発者がtransition: all .3s easeと記述すると、レイアウトプロパティを含むすべてのプロパティの変更がアニメーション化されます。ページ読み込み中、要素がスタイルなしの状態からスタイル付きの状態に移行する際にレイアウトシフトが発生し、これは断続的に起こるため一貫して再現することはほぼ不可能です。私はこのパターンを常に見かけます。

修正方法: レイアウトをトリガーするプロパティを合成(composited)プロパティに置き換えます。

  • top/bottomの代わりにtransform: translateY()を使用する
  • left/rightの代わりにtransform: translateX()を使用する
  • width/heightの代わりにtransform: scale()を使用する
  • 高さの変更と組み合わせたvisibilityの代わりにopacityを使用する
  • 決してtransition: allを使用しない。transition: background-color .2s easeのように正確なプロパティを指定する

transformopacityは完全にコンポジタスレッド上で実行され、決してレイアウトをトリガーしません。完全なデバッグプロセスについては、CSSトランジションによるレイアウトシフトを参照してください。

4. 広告、埋め込み、動的に挿入されるコンテンツ

広告が遅れて読み込まれ、コンテンツを押し下げます。Cookie同意バナーが表示され、ページをシフトさせます。AJAXリクエストが、事前にスペースを確保せずに新しいコンテンツを挿入します。これらはすべて同じ問題です。レンダリング時にブラウザが知らなかったものがページ上に現れるということです。

これらのすべての修正方法は、スペースを確保することです。広告枠の場合、予想される広告サイズに合わせてmin-heightを設定します:

<style>
.ad-slot {
    min-height: 250px;
    contain: layout style;
}
@media (min-width: 600px) {
    .ad-slot { min-height: 90px; }
}
</style>

contain: layout style宣言は、広告コンテナをページの他の部分から分離します。Cookieバナーの場合、コンテンツを押し下げるのではなく、position: fixedを使用してオーバーレイします。AJAXコンテンツの場合、min-heightでスペースを確保します。正確な推測は必要ありません。50pxの不一致は、予約なしによる400pxのシフトよりもはるかにCLSが少なくなります。

YouTubeGoogleマップチャットウィジェットなどのサードパーティの埋め込みには、ファサードパターンを使用します。静的なプレースホルダーを表示し、ユーザーが操作したときにのみ実際の埋め込みを読み込みます。CLSゼロ、無駄なリソースゼロです。

5. スクロール連動のレイアウトシフト

これはLighthouseが決して見つけられないCLSの原因です。Lighthouseはページをスクロールしないため、スクロール連動のレイアウトシフトはラボテストでは完全に見えません。それらを見つける唯一の方法は、RUMデータを使用するか、手動でスクロールしながらPerformanceパネルのトレースを記録することです。

最も一般的な例は、topプロパティをアニメーション化する「スクロールで隠れるヘッダー」です。ほとんどの開発者が知らないことですが、スクロールはLayout Instability仕様において、除外される入力ではありません。クリックとタップには500ミリ秒の猶予があります。スクロールにはありません。スクロールによって引き起こされるすべてのレイアウトシフトは、CLSスコアにカウントされます。

修正方法: スクロール連動のアニメーションには、topの代わりにtransform: translateY()を使用します。パララックス効果、縮小するナビゲーションバー、スクロール連動のプログレスバーにも同じことが当てはまります。スクロール時に動くものは、transformでアニメーション化します。動画例付きの完全なウォークスルーについては、スクロール連動アニメーションがCLSを引き起こす仕組みを参照してください。

クイック修正チェックリスト

CLSの原因 検出方法 修正方法
サイズ未指定の画像/動画 Lighthouseの「サイズが指定されていない画像」監査 widthheightを追加する; CSSからwidth: autoを削除する
ウェブフォントの切り替え RUM: 初回訪問時のみCLSが悪化する フォントメトリクスの上書き; WOFF2のプリロード; フォントのセルフホスト
CSSトランジション すべてのトランジションをリストするコンソールスニペット transition: allを特定のプロパティに置き換える; transform/opacityを使用する
遅れて読み込まれる広告 広告コンテナ要素を示すRUMの要因データ 広告枠にmin-height; contain: layout style
Cookie同意バナー 初回訪問時のCLSスパイク; 要因データにバナーがある コンテンツを押し下げるのではなく、position: fixedオーバーレイを使用する
スクロールアニメーション スクロール中のPerformanceトレース; フィールドCLS > ラボCLS top/left/heighttransformに置き換える

関連記事

すべてのCore Web Vitalsの完全な概要については、Core Web Vitalsハブにアクセスするか、究極のCore Web Vitalsチェックリストを使用してサイト全体を監査してください。

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

何が本当に遅いのか、見つけ出します。

フィールドデータでCritical Rendering Pathをマッピング。Lighthouseレポートではなく、優先順位付きの修正リストをお渡しします。

監査を依頼する
Cumulative Layout Shift (CLS) 問題の特定と修正Core Web Vitals Cumulative Layout Shift (CLS) 問題の特定と修正