了解如何识别和修复布局偏移。
发布时间:2021 年 3 月 11 日,上次更新时间:2025 年 2 月 7 日
本文的第一部分讨论了用于调试布局偏移的工具,第二部分讨论了在识别布局偏移原因时要使用的思路。
工具
您可以使用 Layout Instability API 调试布局偏移,也可以使用 DevTools 等工具,这些工具以更易于理解的格式汇总来自此 API 的数据。
Layout Instability API
Layout Instability API 是浏览器用于衡量和报告布局偏移的机制。所有用于调试布局偏移的工具(包括 DevTools)最终都构建在 Layout Instability API 之上。但是,直接使用 Layout Instability API 是一种强大的调试工具,因为它具有灵活性。
用法
用于衡量累积布局偏移 (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 的组合报告的:LayoutShift
和 LayoutShiftAttribution
接口。以下各节将更详细地解释每个接口。
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 元素。此数组最多可以包含五个来源。如果布局偏移影响的元素超过五个,则会报告布局偏移的五个最大来源(按对布局稳定性的影响衡量)。此信息使用 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 元素。在 DevTools 中将鼠标悬停在此属性上会突出显示相应的页面元素。
previousRect
和 currentRect
属性报告节点的大小和位置。
x
和y
坐标分别报告元素的左上角的 x 坐标和 y 坐标width
和height
属性分别报告元素的宽度和高度。top
、right
、bottom
和left
属性报告与元素的给定边缘对应的 x 或 y 坐标值。换句话说,top
的值等于y
;bottom
的值等于y+height
。
如果 previousRect
的所有属性都设置为 0,则表示该元素已移入视图。如果 currentRect
的所有属性都设置为 0,则表示该元素已移出视图。
解释这些输出时,需要了解的最重要的事情之一是,列为来源的元素是在布局偏移期间偏移的元素。但是,这些元素可能仅与布局不稳定的“根本原因”间接相关。以下是一些示例。
示例 1
此布局偏移将报告一个来源:元素 B。但是,此布局偏移的根本原因是元素 A 的大小发生变化。
示例 2
在此示例中,布局偏移将报告两个来源:元素 A 和元素 B。此布局偏移的根本原因是元素 A 的位置发生变化。
示例 3
在此示例中,布局偏移将报告一个来源:元素 B。更改元素 B 的位置导致了此布局偏移。
示例 4
尽管元素 B 的大小发生变化,但在此示例中没有布局偏移。
查看Layout Instability API 如何报告 DOM 更改的演示。
DevTools
DevTools 提供了许多工具来帮助调试布局偏移。
性能面板
性能面板的实时指标视图允许您与页面交互并监控 CLS 分数,以识别导致大型布局偏移的交互。

一旦您可以可靠地重现布局偏移,就可以执行跟踪以获取更多详细信息

Layout Shift
集群。点击菱形会显示偏移的动画以及摘要面板中的详细信息。布局偏移在布局偏移轨道中突出显示。紫色线将偏移分组到偏移集群中,菱形显示该集群中的各个偏移。菱形的大小与偏移的大小成正比,使您可以专注于最大的偏移。
点击偏移会显示一个弹出窗口,其中包含偏移的动画,并以紫色突出显示元素偏移。
此外,Layout Shift
记录的摘要视图包括开始时间、偏移分数以及偏移的元素。这对于获取有关加载 CLS 问题的更多详细信息特别有帮助,因为这很容易通过重新加载性能配置文件来复制。
这也链接到左侧洞察分析面板中显示的布局偏移罪魁祸首洞察分析,其中显示了顶部的总 CLS,以及布局偏移的可能原因。
有关使用 性能 面板的更多信息,请参阅性能分析参考。
突出显示布局偏移区域
突出显示布局偏移区域可能是一种有用的技术,可以快速、一目了然地了解页面上发生的布局偏移的位置和时间。
要在 DevTools 中启用“布局偏移区域”,请转到设置 > 更多工具 > 渲染 > 布局偏移区域,然后刷新要调试的页面。布局偏移区域将短暂地以紫色突出显示。
用于识别布局偏移原因的思路
无论布局偏移何时或如何发生,您都可以使用以下步骤来识别布局偏移的原因。这些步骤可以补充运行 Lighthouse - 但请记住,Lighthouse 只能识别初始页面加载期间发生的布局偏移。此外,Lighthouse 也只能为某些布局偏移原因提供建议 - 例如,没有显式宽度和高度的图像元素。
识别布局偏移的原因
布局偏移可能是由以下事件引起的
- DOM 元素的位置更改
- DOM 元素的尺寸更改
- 插入或移除 DOM 元素
- 触发布局的动画
特别是,紧接在偏移元素之前的 DOM 元素是最有可能与“导致”布局偏移相关的元素。因此,在调查布局偏移发生的原因时,请考虑
- 前一个元素的位置或尺寸是否发生变化?
- 是否在偏移元素之前插入或移除了 DOM 元素?
- 是否显式更改了偏移元素的位置?
如果前一个元素没有导致布局偏移,请继续搜索,考虑其他前一个元素和附近的元素。
此外,布局偏移的方向和距离可以提供有关根本原因的提示。例如,较大的向下偏移通常表示插入了 DOM 元素,而 1 像素或 2 像素的布局偏移通常表示应用了冲突的 CSS 样式或加载和应用了 Web 字体。

以下是一些最常导致布局偏移事件的特定行为
元素位置的更改(并非由于另一个元素的移动)
此类更改通常是以下原因的结果
- 延迟加载或覆盖先前声明样式的样式表。
- 动画和过渡效果。
元素的尺寸更改
此类更改通常是以下原因的结果
- 延迟加载或覆盖先前声明样式的样式表。
- 在呈现其“插槽”后加载的没有
width
和height
属性的图像和 iframe。 - 在文本呈现后交换字体的没有
width
或height
属性的文本块。
DOM 元素的插入或移除
这通常是以下原因的结果
- 插入广告和其他第三方嵌入。
- 插入横幅广告、警报和模态框。
- 无限滚动和其他 UX 模式,这些模式在现有内容之上加载其他内容。
触发布局的动画
某些动画效果可以触发布局。一个常见的例子是,当通过递增 top
或 left
等属性而不是使用 CSS 的 transform
属性来“动画化”DOM 元素时。阅读如何创建高性能 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});