视觉变化通常是通过 JavaScript 触发的。有时是直接通过样式操作,有时是通过会产生视觉变化的计算(例如搜索数据或将其排序)来进行这些更改。时机不当或长时间运行的 JavaScript 可能是导致性能问题的常见原因,您应当设法尽可能减少其影响。
样式计算
通过添加和移除元素、更改属性、类或播放动画来更改 DOM 会导致浏览器重新计算元素样式,在很多情况下还会重新计算网页的部分或全部布局。此过程称为样式计算。
浏览器通过创建一组匹配的选择器来确定哪些类、伪选择器和 ID 适用于任何给定元素,开始计算样式。然后,它会处理匹配选择器中的样式规则,并计算出此元素的最终样式。
样式重新计算在交互延迟时间中的作用
Interaction to Next Paint (INP) 是一种以用户为中心的运行时性能指标,用于评估网页对用户输入的总体响应情况。该指标用于衡量从用户与网页互动到浏览器绘制下一个帧(显示界面相应的视觉更新)之间的互动延迟时间。
互动的一个重要组成部分是绘制下一帧所需的时间。为了呈现下一帧,所执行的渲染工作由许多部分组成,包括在布局、绘制和合成工作之前进行的页面样式计算。本指南将重点介绍样式计算开销,但减少互动总渲染时长的任何一部分也会降低其总延迟时间。
降低选择器的复杂性
简化 CSS 选择器有助于加快网页的样式计算。最简单的选择器会引用 CSS 中只包含类名的元素:
.title {
/* styles */
}
但是,随着项目规模的扩大,它可能需要更复杂的 CSS,而您最终可能会获得如下所示的选择器:
.box:nth-last-child(-n+1) .title {
/* styles */
}
为了确定这些样式如何应用于页面,浏览器必须有效询问“此元素是否属于 title
类且其父类的 box
是其父元素的-nth-plus-1 子级?浏览器可能需要一些时间才能弄清楚这个问题为简化起见,您可以将选择器更改为更具体的类名称:
.final-box-title {
/* styles */
}
这些替换类名称可能看起来很奇怪,但它们可以让浏览器的工作变得简单得多。例如,在上一个版本中,为了让浏览器知道某个元素是其类型的最后一个元素,它必须先知道有关所有其他元素的所有信息,以确定其后的任何元素是否为 nth-last-child
。与仅根据类名称将选择器与元素进行匹配相比,这种方法的计算开销可能会高得多。
减少要计算样式的元素数量
另一个性能注意事项(通常比选择器复杂性更重要)是元素更改时需要执行的工作量。
一般来说,计算计算的元素样式时,最糟糕的开销就是元素数量乘以选择器数量,因为浏览器需要针对每种样式至少检查每个元素一次,看看它们是否匹配。
样式计算可以直接定位到少量元素,而不是声明整个页面无效。在现代浏览器中,这往往不再是个问题,因为浏览器并不一定需要检查一项更改可能影响的所有元素。另一方面,旧版浏览器有时无法针对此类任务进行优化。您应尽可能减少失效元素的数量。
衡量样式重新计算的开销
您可以通过多种方式衡量浏览器中重新计算样式的开销。这两种方法各有优点,具体取决于您是想在开发环境中的浏览器中衡量,还是想衡量真实用户在您的网站上完成此过程所需的时间。
在 Chrome 开发者工具中衡量样式重新计算的开销
测量样式重新计算开销的方法之一是使用 Chrome DevTools 中的“Performance”面板。如需开始使用,请执行以下操作:
- 打开开发者工具。
- 前往效果标签页。
- 选中选择器统计信息复选框(可选)。
- 点击录制。
- 与网页互动。
停止录制后,您会看到如下图所示的内容:
顶部的条状图是迷你火焰图,还会绘制每秒帧数。activity 越靠近条状标签页底部,浏览器绘制帧的速度就越快。如果您看到火焰图在顶部趋于平稳,并且上面有红色条,则表示有工作会导致帧长时间运行。
在滚动等互动期间出现长时间运行的帧值得仔细研究。如果您看到一个大的紫色块,请放大该 activity,然后选择标记为重新计算样式的任何工作,以详细了解可能耗费大量资源的样式重新计算工作。
点击相应事件即可显示其调用堆栈。如果渲染工作是由用户互动引起的,它会调用触发了样式更改的 JavaScript。该图表还会显示受此更改影响的元素数量(在本例中为 900 多个元素),以及样式计算所用的时间。您可以使用这些信息开始尝试在代码中查找修复。
如果您在跟踪之前勾选了效果面板设置中的选择器统计信息复选框,则轨迹底部的面板中会显示一个同名的额外标签页。
此面板提供有关每个选择器相对费用的实用数据,可帮助您找出费用较高的 CSS 选择器。
如需了解详情,请参阅 CSS 选择器统计信息文档。
衡量真实用户的样式重新计算开销
如果您想知道网站的真实用户需要多长时间才能重新计算样式,Long Animation Frames API 提供了实现此目的所需的工具。此 API 中的数据已添加到 web-vitals
JavaScript 库,包括样式重新计算时间。
如果您怀疑互动呈现延迟是导致网页 INP 的主要原因,则需要确定在该时间段内用于重新计算网页样式的时长。如需了解详情,请参阅如何在现场测量样式重新计算时间。