2025 年还不知道用 content-visibility 加速页面渲染?

传统情况下,对于包含大量内容的网页,浏览器必须一次性处理所有内容,即使是用户还看不到的内容,从而导致页面加载明显变慢。而本文的主角 content-visibility 是一项全新的 CSS 功能,可告知浏览器跳过渲染屏幕外的内容直到用户需要为止。

1. 什么是 CSS Containment

CSS Containment 可以将页面子树与 DOM 的其余部分隔离开来。然后,浏览器可以通过优化这些独立部分的渲染来提高性能。

2025 年还不知道用 content-visibility 加速页面渲染?

容器查询(container query)类似于尺寸媒体查询 (media query),不同之处在于容器查询基于定义为包含上下文(containment context)的特定容器元素的尺寸,而非视口尺寸。容器查询允许查询容器的大小、属性和属性值,以有条件地应用 CSS 样式。

应用这些条件样式时,开发者可以使用容器查询长度单位,这些单位指定相对于查询容器尺寸的长度。定义了其他属性,以便将特定元素建立为查询容器并为其指定特定名称。

总之,CSS Containment 就像将内容放在单独的框中,而每个框都不会影响其他框,因此浏览器可以独立处理。

contain: none;
// 常规渲染,不受任何限制
contain: strict;
// 所有包含规则都应用于元素,相当于 contain: size layout paint style
contain: content;
// 除了 size,其他规则都适用
contain: size;
// 可单独计算元素大小而忽略子元素,不能和 inline-size 一起使用
contain: inline - size;
// 元素内联大小可单独计算而忽略子元素,不能与 size 一起使用
contain: layout;
// 元素外部任何内容都不会影响内部布局,反之亦然
contain: style;
// 对于可影响元素及后代元素属性来说,影响不会超出包含元素的范围
contain: paint;
// 如果后代溢出了包含元素的边界,则会被剪裁

content-visibility: auto 值应用了几种类型的 contain:

  • 样式包含 (Style containment):防止元素内部的样式影响外部元素
  • 布局包含 (Layout containment):防止内部布局更改影响外部布局
  • 绘制包含 (Paint containment):防止内容在视觉上溢出元素

开发者还可以将这些包含类型直接与 contain 属性一起使用:

.container {
  contain: style layout paint;
}

2025 年还不知道用 content-visibility 加速页面渲染?

以上图为例,如果开发者不使用 CSS Containment,即使仅更改单个 item 元素,Chromium 也会花费大量时间进行布局计算,由于其会遍历整个 DOM 树。

而如果 item 使用 contain: strict ,那么当单个 item 发生更改时,浏览器就不需要访问其余节点,即可以停止检查该元素对外部内容的影响。

2.content-visibility 如何工作

content-visibility 属性相当于告知浏览器允许先不渲染用户看不到的内容,从而节省时间,由于浏览器不需要计算屏幕外元素的样式、布局和绘制。

2025 年还不知道用 content-visibility 加速页面渲染?

而当用户滚动页面时,浏览器会及时渲染。最终使得初始页面加载速度更快,尤其是对于包含大量内容的长页面。

content-visibility: visible;
content-visibility: hidden;
content-visibility: auto;

content-visibility 属性接受以上三个值:

  • visible:默认方式,元素的内容按正常方式布局和渲染
  • hidden:元素跳过其内容,且跳过的内容无法响应用户代理功能,例如:在页面中查找、Tab 顺序导航等,不能被选择或聚焦,类似于 display: none
  • auto:元素会启用布局限制 (Layout Containment)、样式限制 (Style Containment) 和绘制限制 (Paint Containment)。如果该元素与用户不相关则会跳过其内容。与 hidden 不同,跳过的内容必须可正常用于用户代理功能,并且可正常聚焦和选择。

设置了 content-visibility: auto 的屏幕外内容仍保留在 DOM 和可访问性树中,从而可以使用 content-visibility: auto 提高页面性能,而不会对可访问性产生负面影响。

由于屏幕外内容的样式不会被渲染,因此使用 display: none 或 visibility: hidden 故意隐藏的元素仍会出目前可访问性树中。如果不希望元素出目前可访问性树中,可以使用 aria-hidden=”true”。

所有现代主流浏览器都支持 content-visibility 属性,包括 Chrome、Firefox、Safari 和 Edge。但是 Firefox 和 Safari 可能会对某些值表现出怪异现象, contain 属性在现代浏览器中得到良好支持。

3. 什么时候应该使用 content-visibility

content-visibility 最适合以下场景:

  • 首屏下方:由于在初始视口外,页面首次加载时不可见
  • 独立部分(不影响页面的其他部分):渲染时不会更改布局,并且无影响其他元素的样式
  • 渲染成本较高(如复杂布局):例如,UI 组件的长列表、Feed 中的博客文章、长评论等

那么何时不提议使用 content-visibility 的?主要聚焦在以下场景:

  • 初始视口中的内容:特别是避免延迟加载 LCP 图像
  • 渲染成本低的小元素:开发者应避免过早优化,仅在 content-visibility 有效时使用
  • 大小可能显著影响页面布局的元素:可能会导致内容渲染不符合预期

下面例子使用 content-visibility 切换元素可见性状态:

// 使用 content-visibility 的 hidden 和 visible 配合 js 手动管理元素可见性
p {
  contain-intrinsic-size: 0 1.1em;
  border: dotted 2px;
}
.hidden > p {
  content-visibility: hidden;
}
.visible > p {
  content-visibility: visible;
}
const handleClick = (event) => {
  const button = event.target;
  const div = button.parentElement;
  button.textContent = div.classList.contains("visible") ? "Show" : "Hide";
  div.classList.toggle("hidden");
  div.classList.toggle("visible");
};

document.querySelectorAll("button.toggle").forEach((button) => {
  button.addEventListener("click", handleClick);
});

4. 为什么 content-visibility 需要和 contain-intrinsic-size 搭配使用

上面示例通过 JS 操作 content-visibility 属性来调整元素的可见性,而 content-visibility: auto 旨在通过自动延迟不在视口(viewport)内的内容的渲染来提升页面加载性能,该属性让浏览器能够基于该元素是否在屏幕可见智能地决定是否渲染。

不过,当开发者使用 content-visibility: auto 时可能会遇到问题,例如:浏览器不知道标记为延迟渲染的内容尺寸有多大。在这种情况下,浏览器会假设高度为 0,从而导致滚动条状态混乱。

而使用 contain-intrinsic-size 则允许开发者为内容指定占位符大小:

.content-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 600px;
   /* 占位符尺寸大小 */
}

对于长内容列表,开发者还可以思考如下方式应用 content-visibility: auto,例如,对于博客文章:

.blog-post:nth-child(n + 10) {
  content-visibility: auto;
  contain-intrinsic-size: auto 600px;
}

这种方式可以确保第一批内容正常渲染,而后续内容使用 content-visibility: auto 自动优化。

5. 本文结论

content-visibility 属性让开发人员能够更好地控制浏览器如何渲染内容,通过告知浏览器跳过渲染屏幕外的内容可以改善页面加载时间和交互性。

关于 content-visibility 需要记住以下要点:

  • 只对屏幕外的内容使用 content-visibility: auto,但需要第一测试性能影响
  • 将其与 contain-intrinsic-size 配对使用,以管理尚未渲染的内容的占位符大小
  • 有选择地应用此技术,以避免重大内容的延迟渲染,例如:LCP 等等

最后值得一提的是,content-visibility:auto 和懒加载并非等价,实则际上相当于懒渲染。对于页面图片等静态资源还是会进行下载,所以当页面有图片等静态资源的时候可以配合 loading=”lazy” 等懒加载方式配合实现性能优化。

参考资料

https://www.debugbear.com/blog/content-visibility-api

https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment

https://developer.mozilla.org/en-US/docs/Web/CSS/contain

https://blogs.igalia.com/mrego/2019/01/11/an-introduction-to-css-containment/

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
又想吃饭了____的头像 - 鹿快
评论 共1条

请登录后发表评论