レイアウト シフトをデバッグする

レイアウト シフトを特定して修正する方法を学習します。

Katie Hempenius
Katie Hempenius

この記事の前半では、レイアウト シフトをデバッグするためのツール、 2 部では、分析を行うときに使う思考プロセスを レイアウト シフトの原因の特定に役立ちます。

ツール

Layout Instability API

Layout Instability API は レイアウト シフトを測定してレポートするためのブラウザ メカニズムです。以下のためのすべてのツール レイアウト シフトのデバッグ(DevTools を含む)は、 Layout Instability APIただし、Layout Instability API を直接使用すると、 優れたデバッグ ツールであり、その柔軟性に優れています。

用途

同じコード スニペットCumulative Layout Shift(CLS)の レイアウト シフトのデバッグに使用できます。以下のスニペットは、レイアウトに関する情報を記録します。 コンソールに移動できますこのログを調べると、 レイアウト シフトがいつ、どこで、どのように発生したかという問題です。

let cls = 0;
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

このスクリプトを実行するときは、次の点に注意してください。

  • buffered: true オプションは、 PerformanceObserver ブラウザーのパフォーマンスエントリ バッファ オブザーバーのスコープより前に作成されたパフォーマンス エントリの 初期化します。その結果、PerformanceObserver はレイアウトをレポートします。 初期化前と初期化後に発生したシフトがすべて記録されます。保持する コンソールログを調べることをおすすめします。初期のレイアウト シフトでは、 報告のバックログを反映しているので、 調整できます。
  • パフォーマンスへの影響を避けるため、PerformanceObserver はメインスレッドが レイアウト シフトについて報告するためにアイドル状態です。その結果 メインスレッドがビジー状態にある場合、 ログに記録されます。
  • このスクリプトは、ユーザー入力から 500 ミリ秒以内に発生したレイアウト シフトを無視します。 CLS にカウントされません

レイアウト シフトに関する情報は、次の 2 つの API を組み合わせて報告します。 LayoutShiftLayoutShiftAttribution インターフェースです。これらの各インターフェースについては、 以降のセクションで説明します

LayoutShift

各レイアウト シフトは、LayoutShift インターフェースを使用して報告されます。内容 エントリは次のようになります。

duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798

上記のエントリはレイアウト シフトを示しており、レイアウト シフトの間に 3 つの DOM 要素が変化しています。 なります。この特定のレイアウト シフトのレイアウト シフトのスコアは 0.175 でした。

これらは、最も関連性の高い LayoutShift インスタンスのプロパティです。 レイアウト シフトのデバッグ:

プロパティ 説明
sources sources プロパティは、レイアウト シフト中に移動した DOM 要素をリストします。この配列には最大 5 つのソースを含めることができます。レイアウト シフトの影響を受ける要素が 5 つ以上ある場合は、レイアウト シフトの影響が大きい上位 5 つ(レイアウトの安定性への影響で測定)が報告されます。この情報は、LayoutShiftAttribution インターフェースを使用して報告されます(詳しくは後述)。
value value プロパティは、特定のレイアウト シフトのレイアウト シフトのスコアをレポートします。
hadRecentInput hadRecentInput プロパティは、ユーザー入力から 500 ミリ秒以内にレイアウト シフトが発生したかどうかを示します。
startTime startTime プロパティは、レイアウト シフトが発生したタイミングを示します。startTime はミリ秒単位で示され、ページの読み込みが開始された時間を基準に測定されます。
duration duration プロパティは常に 0 に設定されます。このプロパティは PerformanceEntry インターフェースから継承されます(LayoutShift インターフェースは PerformanceEntry インターフェースを拡張します)。ただし、期間の概念はレイアウト シフト イベントには適用されないため、0 に設定されます。PerformanceEntry インターフェースの詳細については、仕様をご覧ください。

LayoutShiftAttribution

LayoutShiftAttribution インターフェースは 1 つの DOM の 1 回のシフトを記述する 要素です。レイアウト シフト中に複数の要素がシフトした場合、sources プロパティに複数のエントリが含まれています。

たとえば、以下の JSON は、1 つのソース( <div id='banner'> DOM 要素の y: 76 から下へのシフト y:246

// ...
  "sources": [
    {
      "node": "div#banner",
      "previousRect": {
        "x": 311,
        "y": 76,
        "width": 4,
        "height": 18,
        "top": 76,
        "right": 315,
        "bottom": 94,
        "left": 311
      },
      "currentRect": {
        "x": 311,
        "y": 246,
        "width": 4,
        "height": 18,
        "top": 246,
        "right": 315,
        "bottom": 264,
        "left": 311
      }
    }
  ]

node プロパティは、シフトした HTML 要素を示します。カーソルを合わせると プロパティが表示され、対応するページ要素がハイライト表示されます。

previousRect プロパティと currentRect プロパティは、画像のサイズと位置を報告します。 作成されます。

  • x 座標と y 座標は、x 座標と y 座標をレポートします。 各要素の左上隅に表示されます。
  • width プロパティと height プロパティは、それぞれ幅と高さを報告します。 渡します。
  • toprightbottomleft プロパティは x または y をレポートする 要素のエッジに対応する座標値。その他の 単語の場合、top の値は y と等しくなります。bottom の値は次と等しい y+height

previousRect のすべてのプロパティが 0 に設定されている場合は、要素に ビューにシフトしましたcurrentRect のすべてのプロパティが 0 に設定されている場合は、次のようになります。 要素がビュー外にシフトしたことです

これらの出力を解釈する際に理解しておくべき最も重要なことの一つは、 ソースとしてリストされている要素が、 レイアウト シフトです。ただし、これらの要素は間接的に 問題の「根本原因」に関連する軽減できます。いくつか例を挙げましょう。

例 1

このレイアウト シフトは、1 つのソース(要素 B)とともにレポートされます。ただし、 このレイアウト シフトの根本原因は、要素 A のサイズ変更です。

要素の寸法の変化によるレイアウト シフトの例

例 2

この例のレイアウト シフトは、2 つのソース(要素 A)によって報告されます。 要素 B を指定しますこのレイアウト シフトの根本的な原因は、 要素 A から抽出されます。

要素の位置の変化によるレイアウト シフトの例

例 3

この例のレイアウト シフトは、1 つのソース(要素 B)でレポートされます。 要素 B の位置を変更した結果、このレイアウト シフトが発生しています。

要素の位置の変化によるレイアウト シフトの例

例 4

要素 B のサイズは変化しますが、レイアウト シフトはありません。

要素のサイズが変化するがレイアウト シフトを発生させない例

Layout Instability API が DOM の変更を報告する仕組みのデモをご覧ください。

DevTools

パフォーマンス パネル

DevTools の [Performance] パネルの [Experience] ペインには、 特定のパフォーマンス トレース中に発生するレイアウト シフト(発生した場合も含む) 500 ミリ秒以内に応答するため、CLS にはカウントされません。 [リニューアル版] パネルのハイライト表示で、特定のレイアウト シフトにカーソルを合わせます。 該当する DOM 要素。

DevTools の [Network] パネルに表示されたレイアウト シフトのスクリーンショット

レイアウト シフトの詳細を表示するには、[レイアウト シフト] をクリックして [Summary] ドロワーを開きます。要素のディメンションに加えられた変更のリスト [width, height] の形式を使用します。要素の位置の変更がリストされます。 [x,y] の形式を使用します。[Had 最近の入力] プロパティは、 レイアウト シフトが、ユーザー操作から 500 ミリ秒以内に発生した。

DevTools の [Summary] のスクリーンショットLayout Shift のタブ

レイアウト シフトの期間に関する情報は、[イベントログ] タブで確認できます。 レイアウト シフトの所要時間は、 赤色のレイアウト シフトの長方形の長さの [Experience] ペイン。

DevTools の「イベントログ」のスクリーンショットLayout Shift のタブ

パフォーマンスパネルの使用の詳細については、パフォーマンス 分析 リファレンスをご覧ください。

レイアウト シフト領域をハイライト表示する

レイアウト シフトの領域をハイライト表示すると、 レイアウト シフトの場所とタイミングを一目ですばやく把握できる 表示されます。

DevTools で Layout Shift Regions を有効にするには、[Settings] >その他のツール > レンダリング >Layout Shift Regions を開いてから、デバッグするページを更新します。 レイアウト シフトの領域は紫色で一時的にハイライト表示されます。

レイアウト シフトの原因を特定するための思考プロセス

以下の手順でレイアウト シフトの原因を特定できます レイアウト シフトがいつ、どのように発生するかは問いません。このステップは ただし、Lighthouse を使用すると、 最初のページ読み込み中に発生したレイアウト シフトのみを特定できます。イン また、Lighthouse ではレイアウトの一部の原因に対する提案のみ提供できます。 シフト(たとえば、明示的な幅と高さがない画像要素)が含まれます。

レイアウト シフトの原因を特定する

レイアウト シフトは、次のような場合に発生することがあります。

  • DOM 要素の位置の変更
  • DOM 要素のサイズの変更
  • DOM 要素の挿入または削除
  • レイアウトをトリガーするアニメーション

特に、シフトした要素の直前の DOM 要素は 「原因」に関与している可能性が最も高いレイアウト シフトです。したがって レイアウト シフトが発生した理由を調べるには、以下を検討します。

  • 前の要素の位置や寸法は変化しましたか?
  • シフトした要素の前に DOM 要素が挿入または削除されたか。
  • シフトした要素の位置は明示的に変更されましたか?

前の要素によってレイアウト シフトが起こらなかった場合は、次で検索を続けます。 近接する他の要素も考慮する必要があります。

また、レイアウト シフトの方向と距離からもヒントになります。 特定します。たとえば、大幅に下降したということは、 DOM 要素の挿入ではない場合、レイアウト シフトが 1 ピクセルや 2 ピクセルであれば、 競合する CSS スタイルの適用、または競合する CSS スタイルを 使用します。

<ph type="x-smartling-placeholder">
</ph> フォントの入れ替えによるレイアウト シフトを示す図 <ph type="x-smartling-placeholder">
</ph> この例では、フォントの入れ替えにより、ページ要素が 5 ピクセル上方向にシフトしています。

レイアウト シフトを引き起こす要因として最も頻繁に発生する動作には、次のようなものがあります。 events:

要素の位置の変更(他の要素の移動によるものではない)

この種の変化は、多くの場合、次のような結果によって発生します。

  • 遅れて読み込まれるスタイルシート、または以前に宣言されたスタイルを上書きするスタイルシート。
  • アニメーションと切り替え効果。

要素の寸法の変更

この種の変化は、多くの場合、次のような結果によって発生します。

  • 遅れて読み込まれるスタイルシート、または以前に宣言されたスタイルを上書きするスタイルシート。
  • width 属性と height 属性のない画像と iframe 「スロット」表示されます。
  • width 属性または height 属性のないテキスト ブロックは、 表示されます。

DOM 要素の挿入または削除

多くの場合、次のような原因が考えられます。

  • 広告やその他のサードパーティ埋め込みの挿入。
  • バナー、アラート、モーダルの挿入。
  • 無限スクロールや、上部に追加コンテンツを読み込むその他の UX パターン できます。

レイアウトをトリガーするアニメーション

トリガーされるアニメーション効果には、 あります。共通 例として、DOM 要素が「アニメーション化」されている場合プロパティをインクリメントして CSS を使用せず、topleft など transform プロパティです。高パフォーマンスの CSS アニメーションを作成する方法 をご覧ください。

レイアウト シフトを再現する

再現できないレイアウト シフトは修正できません。シンプルでありながら サイトのレイアウトを把握するのに最も効果的な方法 目標に到達するまでに 5 ~ 10 分かかります。 レイアウト シフトをトリガーできます。その際はコンソールを開いたままにして、 レイアウト シフトに関するレポートを作成するための Layout Instability API

レイアウト シフトを見つけにくい場合は、この演習を 接続速度に応じて異なります特に、低速の 接続速度を測定すると、レイアウト シフトを簡単に特定できます。また debugger ステートメントを使用すると、レイアウトを簡単にステップ実行できるようになります。 できます。

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      debugger;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

最後に、開発中に再現できないレイアウトの問題については、 Layout Instability API とフロントエンド ロギングツールを組み合わせて使用する場合 問題に関するより詳細な情報を収集できます。チェックアウト ページ上で移動された最大要素をトラッキングするコードのサンプルをご覧ください。