
动画卡顿时,很多人会机械地背一句“多用 transform 和 opacity”。这句话方向没错,但如果不了解浏览器渲染链路,就很难判断自己改的是“布局成本”还是“像素绘制成本”。

目录
浏览器大致做了什么
浏览器渲染页面时,通常会经历这样一条链路:
- 计算样式
- 计算布局(layout,也常被称为 reflow)
- 重绘像素
- 合成图层并显示
MDN 的动画性能文档也把 layout 标成了有时被称为 reflow 的步骤。理解这条链路后,性能优化就不是背口诀,而是判断“你改的属性会走到哪一步”。
什么是重排
重排是重新计算元素的位置和几何尺寸,比如宽高、间距、文档流位置。
常见触发源:
width、heightmargin、paddingbordertop、leftdisplay- 插入、删除、移动 DOM
- 先写样式再立刻读
offsetWidth、scrollHeight之类布局信息
重排开销通常比单纯重绘更大,因为浏览器可能要重新计算一片区域,甚至影响后续兄弟元素和父元素布局。
什么是重绘
重绘是布局不变,但需要重新把像素画出来。
常见例子:
colorbackgroundbox-shadowoutline
这类修改一般不需要重新计算盒子位置,但仍要重新绘制视觉结果。
为什么 transform 和 opacity 常更适合动画
MDN 把 transform、opacity 归到了更接近合成阶段的属性。它们通常只需要样式计算,很多情况下甚至不用重新布局或重绘整块内容,因此更容易保持流畅。
一个典型对比:
.bad {
left: 200px;
}
.better {
transform: translateX(200px);
}
left 更容易把元素重新拉回布局计算,transform 更像是在现有结果上做位移。
这也是为什么大多数进入、离开、悬浮动效都优先使用:
transition: transform 200ms ease, opacity 200ms ease;
会把动画写卡的几种模式
1. 动画直接改布局属性
.panel {
transition: width 300ms ease;
}
如果这个面板会推开周围内容,浏览器就要持续重算布局。页面结构越复杂,越容易卡。
2. 频繁读写交替
element.style.width = "200px"
const height = element.offsetHeight
先写再读,浏览器可能被迫立刻刷新布局结果,这类“强制同步布局”在滚动监听和拖拽里尤其常见。
3. 滥用 will-change
.card {
will-change: transform;
}
will-change 不是默认优化开关。提前告诉浏览器做准备会占资源,只有真正频繁变化、且你确认收益明显的元素才值得加。
该怎么优化
- 位移、缩放、淡入淡出,优先改
transform、opacity - 减少会影响周边布局的动画
- 避免在热点逻辑里频繁交替读写布局信息
- 必要时把动画元素和普通文档流解耦
- 用浏览器性能面板看真实瓶颈,不凭感觉优化
如果你的“卡顿”其实伴随着遮罩层、弹窗层级错乱,可能不只是性能问题,还要检查 Stacking Context 与 z-index。
一个更稳的展开思路
很多抽屉或 tooltip 会从下面这样开始:
.drawer {
height: 0;
overflow: hidden;
transition: height 250ms ease;
}
它能工作,但在复杂页面里通常不够省。若产品允许,改成“外层固定布局,内层用 transform / opacity 做视觉移动”往往更流畅。
结论
- 重排关注几何与布局,通常更贵。
- 重绘关注像素更新,通常比重排便宜,但也不是零成本。
transform、opacity更适合多数 UI 动画,因为更容易停留在更轻的渲染阶段。- 性能优化应该先看渲染链路,再看属性选择,而不是只背 API 名单。
如果你下一步是在做 Tailwind 或组件动画,可以配合看 Tailwind CSS 4 入门 和 Framer Motion 指南。
参考资料
继续阅读
css中的3d使用:深入理解 CSS Perspective 与 Transform-Style
和是 CSS 3D 变换中不可或缺的两个属性。赋予了场景深度,模拟了观察者的视觉体验;而则决定了子元素如何在 3D 空间中呈现。掌握这两个属性的用法,将为您的网页设计带来更丰富的视觉层次和更具吸引力的交互体验。现在,不妨动手尝试一下,释放您的创意,打造出令人惊叹的 3D 世界吧!
10 分钟深入理解CSS对齐属性:align-items, align-self, justify-items, justify-self
属性作用对象方向适用布局覆盖关系容器垂直Flex/Grid被align-self覆盖align-self子项垂直Flex/Grid覆盖容器水平Grid被覆盖子项水平Grid覆盖记忆口诀想调垂直用align,想调水平用justify容器设置用-items,单个调整用-selfGri
5 分钟CSS 继承与重置:initial、inherit、unset 怎么选
把 initial、inherit、unset 的差异放到真实 CSS 场景里讲清楚,并说明哪些属性默认会继承、哪些不会,避免把重置和继承写反。
订阅 FreeMac
每周精选:免费 Mac 软件评测、可信来源更新、替代方案和少折腾指南。