content-visible:可提升渲染性能的新 CSS 属性

通过跳过渲染屏幕外内容来缩短初始加载时间。

Vladimir Levin
Vladimir Levin

通过 content-visibility 媒体资源,它在 Chromium 85 中推出,可能是影响力最大的新 CSS 之一 用于提高网页加载性能的属性。content-visibility 启用 让用户代理跳过元素的呈现工作,包括布局和绘制 直到需要时为止。由于系统会跳过呈现,因此如果视频的很大一部分 内容在屏幕外,利用 content-visibility 属性可让 初始用户加载速度会更快它还可以让您更快地与 。这挺好看的。

包含代表广告网络成效的图表的演示
在我们的文章演示中,将 content-visibility: auto 应用于分块内容区域可在初始加载时将渲染性能提升 7 倍。请阅读下文了解详情。

浏览器支持

浏览器支持

  • Chrome:85。 <ph type="x-smartling-placeholder">
  • 边缘:85。 <ph type="x-smartling-placeholder">
  • Firefox:125. <ph type="x-smartling-placeholder">
  • Safari:18。 <ph type="x-smartling-placeholder">

来源

content-visibility 依赖于“CSS 包含”中的基元 Spec。虽然只有 content-visibility Chromium 85 中目前支持此功能(并且被视为“值得 “原型设计” (适用于 Firefox),则大多数现代操作系统都支持包含规范 浏览器

CSS Containment

CSS 容器的主要目标是通过可预测地将 DOM 子树与网页的其余部分隔离,从而提升网页内容的渲染性能。

基本上,开发者可以告诉浏览器被封装的页面的哪些部分 视为一组内容,让浏览器能够推断内容, 因此需要考虑子树之外的状态。了解哪段内容 (子树)包含隔离的内容意味着浏览器可以进行优化, 网页呈现方面的决策

CSS 有 4 种类型 包含、 每个是 contain CSS 属性的可能值,这可以合并 以空格分隔的值列表:

  • size:元素的尺寸包含确保了元素的框 而无需检查其后代。这意味着我们可以 如果我们只需要 元素。
  • layout:布局包含意味着子级不会影响 网页上其他框的外部布局。这样,如果我们只想排列其他框,则可以跳过子孙布局。
  • style:样式包含可确保 不仅仅是其后代不会转义元素(例如计数器)。这个 我们或许可以跳过对后代节点的样式计算, 计算其他元素的样式。
  • paint:Paint Streets 可确保包含框的后代 也不会显示在其边界之外任何内容都不能明显溢出元素 如果某个元素在屏幕外或因其他原因不可见,其后代就会 也不会显示这样一来,如果元素不在屏幕上,我们就可以跳过绘制其子项。

使用 content-visibility 跳过渲染工作

可能很难确定要使用哪些包含值,因为浏览器 只有在指定了合适的集合时,系统才会开始进行优化。您可以 您可以尝试修改这些价值 最佳,或者 可以使用另一个名为content-visibility的 CSS 属性来应用所需的 自动限制。content-visibility可确保 性能上的提升 开发者。

content-visibility 属性接受多个值,但属性是 auto 可立竿见影地提升性能一个元素,它具有 content-visibility: auto 获得 layoutstylepaint 控制。如果元素位于屏幕之外(并且与用户没有其他关联,相关元素是指其子树中具有焦点或处于选中状态的元素),则它也会获得 size 容器(并且会停止绘制对其内容进行点击测试)。

这是什么意思?简而言之,如果元素在屏幕外,其后代将 未呈现。浏览器在确定元素大小时不考虑 其任何内容,它就会停止。大部分渲染,例如样式设置 元素子树的布局和布局。

当元素接近视口时,浏览器不再添加 size 并开始绘制和点击测试元素的内容。这个 使渲染工作能够及时完成,以供用户看到。

关于无障碍功能的说明

content-visibility: auto 的一个特性是,屏幕外的内容在文档对象模型中仍然可用,因此,无障碍树也在可访问性树(与 visibility: hidden 不同)。这意味着,用户可以在网页上搜索并导航到这些内容,而无需等待内容加载或牺牲呈现性能。

不过,具有 display: nonevisibility: hidden 等样式特征的 landmark 元素在屏幕外时也会出现在无障碍树中,因为浏览器只有在进入视口后才会呈现这些样式。为防止这些内容在无障碍树中显示(从而可能造成混乱),请务必同时添加 aria-hidden="true"

示例:旅游博客

<ph type="x-smartling-placeholder">
在此示例中,我们将右侧的旅游博客设为基准,并将 content-visibility: auto 应用于左侧的分块区域。结果显示,网页初始加载时呈现时间从 232 毫秒30 毫秒

旅游博客通常包含一系列带几张图片的故事, 说明文字。以下是在典型浏览器中转到 旅游博客:

  1. 系统会从网络下载网页的部分内容, 资源。
  2. 浏览器会设置网页的所有内容的样式并进行布局,而不会考虑这些内容是否对用户可见。
  3. 浏览器将返回到第 1 步,直到所有页面和资源 已下载。

在第 2 步中,浏览器会处理所有内容,以寻找可能 都发生了哪些变化它会更新所有新元素的样式和布局,以及 可能已因新更新而发生变化的元素。这是渲染 工作。这需要时间。

一个旅游博客的屏幕截图。
一个旅游博客示例。请参阅 Codepen 上的演示

现在考虑一下,将 content-visibility: auto 放在每个 单个故事。一般循环相同:浏览器下载并渲染网页的部分内容。不过,不同之处在于 在第 2 步中完成的工作量。

借助内容可见性,它会设置所有 当前对用户可见(他们在屏幕上)。不过,在处理 故事完全位于屏幕外时,浏览器会跳过渲染工作, 只为元素框本身设置样式和布局

加载此页面的效果就像其中包含完整的屏幕内故事,以及每个屏幕外故事对应的空白框。这在很大程度上 而且预计可减少 50% 或更多 正在加载。在示例中,我们看到呈现时间从 232 毫秒增加到了 30 毫秒的呈现时间。性能是原来的 7 倍

您需要完成哪些工作才能获得这些好处?首先,我们 将内容分块:

使用 CSS 类将内容分成多个部分且带注解的屏幕截图。
示例:将内容分块为应用了 story 类的部分,以接收 content-visibility: auto。查看 Codepen 上的演示

然后,我们将以下样式规则应用于这些版块:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

使用 contain-intrinsic-size 指定元素的自然尺寸

为了发挥 content-visibility 的潜在优势,浏览器 因此需要应用尺寸包含机制 不会以任何方式影响元素的尺寸。这意味着 显示时会显示为空白。如果没有为元素指定高度 那么其高度将为 0。

这可能不太理想,因为滚动条的大小会发生变化,具体取决于每个故事的高度是否为零。

幸运的是,CSS 还提供了另一个属性 contain-intrinsic-size, 可有效指定元素的自然尺寸,前提是 受尺寸包含性影响。在我们的示例中,我们将其设置为 1000px,以估算各个部分的高度和宽度。

这意味着它的布局方式就像有一个“intrinsic-size”的子项一样 尺寸,以确保未调整大小的 div 仍然占据空间。 contain-intrinsic-size 充当占位符大小,取代渲染内容。

在 Chromium 98 及更高版本中,auto contain-intrinsic-size的关键字。如果指定了这些标记,浏览器就会记住 上次呈现的尺寸(如果有),并使用该尺寸,而不是开发者提供的占位符 。例如,如果您指定了 contain-intrinsic-size: auto 300px,则 元素最初的每个维度都采用 300px 的固有大小,但一次 元素的内容时,它会保留所呈现的固有尺寸。 系统也会记住所有后续渲染尺寸更改。实际上,这意味着 滚动应用了 content-visibility: auto 的元素,然后将其滚动回 屏幕外,则会自动保持理想的宽度和高度,且不会还原 占位符大小。这项功能对于无限滚动用户尤为有用 现在,它可以根据用户情况,自动改进大小估算 浏览网页。

使用 content-visibility: hidden 隐藏内容

如果您想让内容保持未渲染状态(无论其是否显示在屏幕上),同时利用缓存的渲染状态带来的好处,该怎么办?请输入: content-visibility: hidden

content-visibility: hidden资源可为您提供 与 content-visibility: auto 一样,未呈现内容和缓存呈现状态 屏幕外不过,与 auto 不同,它不会自动开始 在屏幕上呈现。

这赋予了您更多掌控力,让您可以隐藏元素的内容并 以便稍后快速取消隐藏它们

将其与隐藏元素内容的其他常用方法进行比较:

  • display: none:隐藏元素并销毁其渲染状态。这意味着,取消隐藏元素的开销与渲染具有相同内容的新元素的开销一样高。
  • visibility: hidden:隐藏元素并保持其渲染状态。这个 该元素并不会真正从文档中移除,因为它(及其子树) 仍然会占据网页上的几何图形空间,并且仍可点击。它 还可以在需要时随时更新呈现状态(即使处于隐藏状态)。

另一方面,content-visibility: hidden 会在 以便保留其呈现状态 它们只会在相应元素再次显示时才会发生(即 content-visibility: hidden 属性已移除)。

content-visibility: hidden 的一些很好的用例是, 高级虚拟滚动条和测量布局。它们也非常适合单页应用 (SPA)。非活跃应用视图可通过以下方式留在 DOM 中: 已应用content-visibility: hidden,以阻止其展示,但其 缓存状态这样一来,当视图再次处于活动状态时,就可以快速渲染该视图。

对下一次绘制的交互的影响 (INP)

INP 是一个指标,用于评估网页能否可靠地响应用户输入。响应速度可能会受到主线程上发生的过多工作(包括渲染工作)的影响。

只要能减少任意给定页面上的渲染工作,主线程便有机会更快地响应用户输入。这包括渲染工作,在适当情况下使用 content-visiblity CSS 属性可以减少渲染工作,尤其是在启动期间(此时完成了大部分渲染和布局工作)。

减少渲染工作会对 INP 产生直接影响。当用户尝试与正确使用 content-visibility 属性的页面互动时,系统会延迟屏幕外元素的布局和渲染,从而赋予主线程响应用户可见的关键工作的机会。在某些情况下,这样做可以提高网页的 INP。

总结

content-visibility 和 CSS 包含规范意味着一些令人兴奋的效果 Boost 会直接应用到您的 CSS 文件中。如需详细了解 属性,请查看: