缩小样式计算的范围并降低其复杂性

视觉变化通常是通过 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”面板。如需开始使用,请执行以下操作:

  1. 打开开发者工具。
  2. 前往效果标签页。
  3. 选中选择器统计信息复选框(可选)。
  4. 点击录制
  5. 与网页互动。

停止录制后,您会看到如下图所示的内容:

DevTools 显示样式计算。
显示样式计算的 DevTools 报告。

顶部的条状图是迷你火焰图,还会绘制每秒帧数。activity 越靠近条状标签页底部,浏览器绘制帧的速度就越快。如果您看到火焰图在顶部趋于平稳,并且上面有红色条,则表示有工作会导致帧长时间运行。

在 Chrome 开发者工具中填充的性能面板的活动摘要中,放大 Chrome 开发者工具中的问题区域。
DevTools 活动摘要中的长时间运行的帧。

在滚动等互动期间出现长时间运行的帧值得仔细研究。如果您看到一个大的紫色块,请放大该 activity,然后选择标记为重新计算样式的任何工作,以详细了解可能耗费大量资源的样式重新计算工作。

获取长时间运行的样式计算的详细信息,包括重要信息,例如受样式重新计算工作影响的元素数量。
在开发者工具摘要中长期运行的样式重新计算,用时超过 25 毫秒。

点击相应事件即可显示其调用堆栈。如果渲染工作是由用户互动引起的,它会调用触发了样式更改的 JavaScript。该图表还会显示受此更改影响的元素数量(在本例中为 900 多个元素),以及样式计算所用的时间。您可以使用这些信息开始尝试在代码中查找修复。

如果您在跟踪之前勾选了效果面板设置中的选择器统计信息复选框,则轨迹底部的面板中会显示一个同名的额外标签页。

CSS 选择器统计信息表,显示在 Chrome 开发者工具的“性能”面板中。此表包含标题和相应数据,例如经过的时间、匹配尝试次数、匹配次数、不匹配节点的百分比、选择器以及可在其中找到这些选择器的样式表。
选择器统计信息表,如 Chrome DevTools 的“Performance”面板中所示。

此面板提供有关每个选择器相对费用的实用数据,可帮助您找出费用较高的 CSS 选择器。

如需了解详情,请参阅 CSS 选择器统计信息文档

衡量真实用户的样式重新计算开销

如果您想知道网站的真实用户需要多长时间才能重新计算样式,Long Animation Frames API 提供了实现此目的所需的工具。此 API 中的数据已添加到 web-vitals JavaScript 库,包括样式重新计算时间。

如果您怀疑互动呈现延迟是导致网页 INP 的主要原因,则需要确定在该时间段内用于重新计算网页样式的时长。如需了解详情,请参阅如何在现场测量样式重新计算时间

资源