调试布局偏移

了解如何识别和修正布局偏移。

Katie Hempenius
Katie Hempenius

本文的第一部分讨论了用于调试布局偏移的工具, 而第二部分则讨论在设计模型时 确定布局偏移的原因。

工具

布局不稳定 API

Layout Instability API 是 衡量和报告布局偏移的浏览器机制。所有工具 调试布局偏移(包括开发者工具)最终在 布局不稳定 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。

结合使用以下两种 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

上面的条目表示布局偏移,其中三个 DOM 元素发生了更改 排名。此次布局偏移的布局偏移得分为 0.175

这些是与以下查询最相关的 LayoutShift 实例属性: 调试布局偏移:

属性 说明
sources sources 属性会列出在布局偏移期间移动的 DOM 元素。此数组最多可包含五个源。如果受布局偏移影响的元素超过 5 个,系统会报告布局偏移影响最大的五个来源(根据对布局稳定性的影响进行衡量)。此信息通过 LayoutShiftAttribution 接口进行报告(下文有详细说明)。
value value 属性会报告特定布局偏移的布局偏移得分
hadRecentInput hadRecentInput 属性指示布局偏移是否发生在用户输入后的 500 毫秒内。
startTime startTime 属性用于指明布局偏移的时间。startTime 以毫秒为单位,其衡量依据为网页加载的开始时间
duration duration 属性将始终设置为 0。此属性继承自 PerformanceEntry 接口(LayoutShift 接口扩展了 PerformanceEntry 接口)。不过,持续时间的概念不适用于布局偏移事件,因此它设置为 0。如需了解 PerformanceEntry 接口,请参阅规范

LayoutShiftAttribution

LayoutShiftAttribution 接口描述了单个 DOM 的一次偏移 元素。如果在布局偏移期间多个元素发生偏移,则 sources 属性包含多个条目。

例如,下面的 JSON 对应于一个来源的布局偏移: 将 <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 元素。将鼠标悬停在此项 属性突出显示相应的页面元素。

previousRectcurrentRect 属性会报告 节点。

  • xy 坐标会报告 x 坐标和 y 坐标 分别对应元素的
  • widthheight 属性分别报告宽度和高度 元素。
  • toprightbottomleft 属性报告 x 或 y 坐标值。在其他 则 top 的值等于 ybottom的值等于 y+height

如果 previousRect 的所有属性都设为 0,则意味着该元素具有 转移到了用户视野中如果 currentRect 的所有属性都设置为 0,则意味着 元素离开了视图

在解读这些输出时,要了解的最重要的内容之一 列为的元素是在 布局偏移不过,这些元素可能只是间接地 是与“根本原因”相关的布局不稳定的原因以下是几个例子。

示例 1

此布局偏移将通过一个来源(元素 B)进行报告。不过, 这种布局偏移的根本原因是元素 A 的尺寸发生变化。

显示因元素尺寸变化而导致的布局偏移的示例

示例 2

此示例中的布局偏移通过两个来源进行报告:元素 A 和元素 B。这种布局偏移的根本原因是 元素 A。

显示元素位置变化导致的布局偏移的示例

示例 3

此示例中的布局偏移通过一个来源(元素 B)进行报告。 元素 B 的位置发生变化导致了布局偏移。

显示元素位置变化导致的布局偏移的示例

示例 4

虽然元素 B 更改了大小,但在本例中没有布局偏移。

示例:元素改变了大小,但不会导致布局偏移

查看展示 Layout Instability API 如何报告 DOM 更改的演示

开发者工具

性能面板

开发者工具 Performance 面板的 Experience 窗格显示了全部 在给定性能跟踪期间发生的布局偏移,即使发生 500 毫秒以内,因此不会计入 CLS。 将鼠标悬停在体验面板中突出显示的特定布局偏移上 受影响的 DOM 元素。

开发者工具 Network 面板中显示的布局偏移的屏幕截图

如需查看有关布局偏移的更多信息,请点击“布局偏移”,然后 打开摘要抽屉式导航栏。系统会列出对元素尺寸所做的更改 使用 [width, height] 格式;元素位置的变化 使用 [x,y] 格式。有最近输入属性用于指明 布局在用户互动发生后的 500 毫秒内发生偏移。

开发者工具“摘要”的屏幕截图进行布局偏移的 Tab 键

如需了解布局偏移的持续时间,请打开 Event Log 标签页。 布局偏移的持续时间也可通过查看 体验窗格,其中显示了红色布局偏移矩形的长度。

开发者工具“Event Log”的屏幕截图进行布局偏移的 Tab 键

如需详细了解如何使用“性能”面板,请参阅性能 “分析”部分 参考文档

突出显示布局偏移区域

突出显示布局偏移区域是获取 快速一览布局偏移的位置和时间 网页上发生的所有事件

如需在开发者工具中启用布局偏移区域,请依次前往 Settings >更多工具 > 渲染 >Layout Shift Regions,然后刷新要调试的页面。 布局偏移的区域将以紫色短暂突出显示。

确定布局偏移原因的思考过程

您可以使用以下步骤找出导致布局偏移的原因 无论布局偏移何时或以何种方式发生。您可以 但需要注意的是,Lighthouse 只识别初始网页加载期间发生的布局偏移。在 此外,Lighthouse 也只能提供一些 偏移 - 例如,没有明确宽度和高度的图片元素。

确定布局偏移的原因

以下事件可能会导致布局偏移:

  • DOM 元素位置的更改
  • DOM 元素尺寸更改
  • 插入或移除 DOM 元素
  • 触发布局的动画

具体而言,紧跟在偏移的元素前面的 DOM 元素是 最有可能导致这种情况的布局偏移因此,如果 要调查布局偏移的原因,请考虑以下事项:

  • 前一个元素的位置或尺寸是否发生了变化?
  • 是否在偏移的元素之前插入或移除了 DOM 元素?
  • 偏移元素的位置是否被明确更改了?

如果前面的元素未导致布局偏移,请在以下时间后继续搜索: 考虑其他前面和相邻的元素。

此外,布局偏移的方向和距离可以提供 根本原因。例如,大幅下移通常表示 DOM 元素插入,而 1 像素或 2 像素的布局偏移通常表示 有冲突的 CSS 样式的应用,或加载和应用 网页字体。

<ph type="x-smartling-placeholder">
</ph> 显示字体交换导致的布局偏移的示意图 <ph type="x-smartling-placeholder">
</ph> 在本示例中,字体交换导致页面元素向上偏移 5 个像素。

下面列出了一些最常导致布局偏移的具体行为 事件:

元素位置的变化(并非由其他元素移动导致)

此类变化通常是由以下原因导致的:

  • 样式表加载延迟或覆盖之前声明的样式。
  • 动画和过渡效果。

元素尺寸更改

此类变化通常是由以下原因导致的:

  • 样式表加载延迟或覆盖之前声明的样式。
  • 不包含 widthheight 属性的图片和 iframe 其“槽位”已渲染。
  • 没有 widthheight 属性的文本块,这些属性可在 文本已呈现。

插入或移除 DOM 元素

这通常是由以下原因导致的:

  • 插入广告和其他第三方嵌入内容。
  • 插入横幅、提醒和模态窗口。
  • 无限滚动以及会在上方加载其他内容的其他用户体验模式 现有内容。

触发布局的动画

有些动画效果可以触发 布局。常见 例如,当 DOM 元素为“动画”时增加属性 (例如 topleft),而不要使用 CSS 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 与前端日志记录工具结合使用 来收集有关这些问题的更多信息。结账 用于跟踪网页上最大偏移元素的代码示例。