content-visibility: auto —— 让浏览器跳过离屏渲染的性能黑科技

问题场景

页面越来越长,一个商品列表页挂了 200 个卡片,每个卡片里有图片、评分星星、价格标签、促销气泡。首屏加载时 DevTools Performance 面板显示:首次渲染花了 1.8s,其中 60% 的时间花在了屏幕外的 DOM 上

滚动时更糟:滚轮一动就掉帧,因为浏览器在不停地为每个离屏元素做样式计算(style recalc)和布局(layout)。

传统优化手段(懒加载图片、虚拟滚动)都只能治标:图片懒加载只省了网络请求,DOM 节点的样式计算和布局开销一分没少;虚拟滚动则要重写整个列表组件,成本太高。

原因分析

浏览器渲染管线是:解析 DOM → 样式计算 → 布局 → 绘制 → 合成 。问题在于,浏览器默认会为所有可见性未知的元素执行完整的样式计算和布局,哪怕它远在屏幕之外。

对于长页面,离屏元素占了 DOM 的绝大部分,这些计算全是浪费 ------ 用户根本看不到,浏览器却白干了几百毫秒的活。

解决方案:content-visibility

content-visibility 是 Chromium 85+ 提供的原生属性,核心思想就一句话:告诉浏览器"这块内容暂时不用渲染,等它快进入视口时再算"

css 复制代码
.card {
  /* 核心用法 */
  content-visibility: auto;

  /* 关键配套:给离屏内容一个预估高度,避免出现滚动条跳动 */
  contain-intrinsic-size: auto 300px;
}

为什么必须配 contain-intrinsic-size?

content-visibility: auto 会让离屏元素跳过渲染,但元素的实际高度此时是未知的 ------ 浏览器不知道它该占多大空间,滚动条会疯狂跳动,页面"越滚越长"。

contain-intrinsic-size 就是给浏览器一个"占位高度"的预估:

css 复制代码
/* 固定预估 */
contain-intrinsic-size: 300px;

/* auto 关键字:记住上次渲染后的真实尺寸,更精准 */
contain-intrinsic-size: auto 300px;

auto 模式下,元素第一次离屏用 300px 占位;一旦渲染过,就记住真实高度,后续滚动回来不再抖动。

实战:商品卡片列表

html 复制代码
<div class="product-list">
  <div class="card">
    <img src="p1.jpg" loading="lazy" alt="商品1">
    <h3>无线降噪耳机</h3>
    <p class="price">¥899 <s>¥1299</s></p>
    <span class="tag">限时折扣</span>
  </div>
  <!-- ... 一共 200 个 card ... -->
</div>
css 复制代码
.card {
  content-visibility: auto;
  contain-intrinsic-size: auto 280px;
}

配合 loading="lazy" 图片懒加载,双管齐下:

  • loading="lazy"网络请求
  • content-visibility: auto渲染计算

实测:200 个卡片的列表页,首次渲染时间从 1.8s 降到 0.6s,滚动掉帧基本消失。

进阶:跳过不可见区块的渲染

长文博客的场景,正文中间的评论区、相关推荐这些"非核心区块",可以直接用 content-visibility: hidden 让浏览器完全不渲染 (区别于 auto 的按需渲染):

css 复制代码
.comments-section {
  content-visibility: hidden;
}

注意:hiddendisplay: none 不同,它保留元素的布局占位,但跳过绘制,适合"存在但暂时不需要展示"的内容。

避坑要点

  1. 兼容性:Chromium 85+ 支持,Safari 16.4+、Firefox 125+ 才支持。老浏览器直接忽略该属性,页面功能不受影响,只是性能提升失效 ------ 是渐进增强的完美候选。
  2. 必须配 contain-intrinsic-size:否则滚动条抖动,体验反而更差。
  3. 不要用在首屏关键内容上:首屏内容本来就要立刻渲染,加了反而可能延迟出现。
  4. content-visibility: auto 的元素对 position: sticky 子元素有影响 :离屏时会跳过渲染,sticky 定位可能失效,需要测试。
  5. 与虚拟滚动的关系:虚拟滚动解决的是"DOM 节点太多"的问题(万级节点),content-visibility 解决的是"渲染计算浪费"的问题(百千级节点)。节点量级小用后者,量大才上虚拟滚动。

要点总结

  • content-visibility: auto = 离屏元素跳过渲染,进入视口前才计算,是渲染性能的懒加载
  • contain-intrinsic-size 是它的最佳搭档,防止滚动条跳动
  • 懒加载图片(省网络)+ content-visibility(省计算)组合使用,长列表性能翻倍
  • 渐进增强特性,老浏览器自动降级,放心用
相关推荐
小鹰信息技术服务部1 小时前
Edge安装包MicrosoftEdgeSetup.exe无法运行,点击没反应
前端·edge
webkubor2 小时前
一次前端生产白屏复盘:旧 HTML、Hash 资源和 MIME type text/html
前端·前端工程化
咩咩啃树皮2 小时前
第63篇【终极整合巨作】从零手写原生中后台管理系统|整合62篇全部前端知识点|从头到尾完整架构+全功能逻辑
前端·架构
Highcharts3 小时前
用Highcharts如何动态向一个序列添加点-示列讲解
前端
weixin_431600443 小时前
做 Agent 会用到的 Node API(4):取消与 AbortController
前端·学习·ai·agent·ai编程
JiaLin_Denny3 小时前
Vue3中ref和reactive用法与双向数据绑定
前端·javascript·vue.js
用户2181697049303 小时前
Flutter(十)Container Center Align
前端
无人生还4 小时前
从 Vue3 到 React · 快速上手系列第 12 篇:并发特性与性能优化
前端·vue.js·react.js
小p4 小时前
nextjs学习9: Next.js 渲染与缓存
前端·后端