了解如何识别和修正布局偏移。
本文的第一部分讨论了用于调试布局偏移的工具, 而第二部分则讨论在设计模型时 确定布局偏移的原因。
工具
Layout Instability API
Layout Instability API 是 衡量和报告布局偏移的浏览器机制。用于调试布局偏移的所有工具(包括 DevTools)最终都基于布局不稳定性 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 元素。此数组最多可包含五个源。如果有超过 5 个元素受到布局偏移的影响,系统会报告导致布局偏移的 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 元素。将鼠标悬停在此项
属性突出显示相应的页面元素。
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 更改了大小,但在本例中没有布局偏移。
查看演示,了解布局不稳定性 API 如何报告 DOM 更改。
开发者工具
“性能”面板
开发者工具 Performance 面板的 Experience 窗格会显示给定性能轨迹期间发生的所有布局偏移,即使这些偏移发生在用户互动后的 500 毫秒内,因此不会计入 CLS 也不例外。在体验面板中将鼠标悬停在特定布局偏移上,系统会突出显示受影响的 DOM 元素。
如需查看有关布局偏移的更多信息,请点击“布局偏移”,然后
打开摘要抽屉式导航栏。系统会列出对元素尺寸所做的更改
使用 [width, height]
格式;元素位置的变化
使用 [x,y]
格式。Had recent input 属性表示布局是否在用户互动后的 500 毫秒内发生了偏移。
如需了解布局偏移的持续时间,请打开 Event Log 标签页。 布局偏移的持续时间也可通过查看 体验窗格,其中显示了红色布局偏移矩形的长度。
如需详细了解如何使用效果面板,请参阅效果分析参考文档。
突出显示布局偏移区域
突出显示布局偏移区域是一种有用的技术,可让您快速一目了然地了解页面上发生的布局偏移的位置和时间。
如需在 DevTools 中启用布局偏移区域,请依次前往设置 > 更多工具 > 渲染 > 布局偏移区域,然后刷新要调试的网页。布局偏移区域会以紫色短暂突出显示。
确定布局偏移原因的思考过程
无论布局偏移发生的时间或方式如何,您都可以按照以下步骤找出布局偏移的原因。您可以通过运行 Lighthouse 来补充这些步骤,但请注意,Lighthouse 只能识别在初始页面加载期间发生的布局偏移。此外,Lighthouse 也只能针对导致布局偏移的一些原因(例如,没有明确宽度和高度的图片元素)提供建议。
确定布局偏移的原因
布局偏移可能由以下事件引起:
- DOM 元素位置的更改
- DOM 元素尺寸更改
- 插入或移除 DOM 元素
- 触发布局的动画
具体而言,紧跟在偏移的元素前面的 DOM 元素是 最有可能导致这种情况的布局偏移因此,如果 要调查布局偏移的原因,请考虑以下事项:
- 前一个元素的位置或尺寸是否发生了变化?
- 是否在偏移的元素之前插入或移除了 DOM 元素?
- 偏移元素的位置是否被明确更改了?
如果前面的元素未导致布局偏移,请在以下时间后继续搜索: 考虑其他前面和相邻的元素。
此外,布局偏移的方向和距离可以提供有关根本原因的提示。例如,大幅下移通常表示 DOM 元素插入,而 1 像素或 2 像素的布局偏移通常表示 有冲突的 CSS 样式的应用,或加载和应用 网页字体。
下面列出了一些最常导致布局偏移的具体行为 事件:
元素位置的变化(并非由其他元素移动导致)
此类变化通常是由以下原因导致的:
- 延迟加载或覆盖之前声明的样式的样式表。
- 动画和过渡效果。
元素尺寸更改
此类变化通常是由以下原因导致的:
- 较晚加载或覆盖之前声明的样式的样式表。
- 不包含
width
和height
属性的图片和 iframe 其“槽位”已渲染。 - 没有
width
或height
属性的文本块,这些属性可在 文本已呈现。
插入或移除 DOM 元素
这通常是以下原因所致:
- 插入广告和其他第三方嵌入内容。
- 插入横幅、提醒和模态窗口。
- 无限滚动以及会在上方加载其他内容的其他用户体验模式 现有内容。
触发布局的动画
某些动画效果可以触发布局。一个常见的示例是,通过递增 top
或 left
等属性(而不是使用 CSS 的 transform
属性)来为 DOM 元素添加“动画效果”。如需了解详情,请参阅如何创建高性能 CSS 动画。
重现布局偏移
您无法修复无法重现的布局偏移。若要更好地了解网站的布局稳定性,最简单但最有效的方法之一就是花 5-10 分钟与您的网站互动,以触发布局偏移。在此过程中,请保持控制台处于打开状态,并使用布局不稳定性 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});
最后,对于在开发过程中无法重现的布局问题,不妨考虑将布局不稳定性 API 与您选择的前端日志记录工具结合使用,以收集有关这些问题的更多信息。请参阅有关如何跟踪网页上移位幅度最大的元素的代码示例。