只用 transform 和 opacity 做 transition 可确保全程走合成层,不触发 layout 或全量 paint;其他属性如 width、left、color 等会进入 layout 或 paint 阶段,易引发 layout shift 和帧率波动。

只对 transform 和 opacity 做 transition
浏览器渲染流水线中,只有 transform 和 opacity 能保证全程走合成层(compositor),不触发 layout 或全量 paint。其他属性——哪怕只是 color 或 background-color——都属于 paint 阶段,高频变化时帧率易波动。
常见错误是写 transition: all 0.3s,结果 hover 时悄悄把 width、margin 也拖进动画,一卡就暴露问题。
- ✅ 正确写法:
transition: transform 0.3s ease, opacity 0.3s ease - ❌ 错误写法:
transition: width 0.3s, left 0.3s(直接触发布局重排) - ⚠️ 注意:
opacity值必须是小数,opacity: 0.5可,opacity: 50%不合法,会降级为无效声明
位移动画必须用 translateX/Y/Z 替代 top/left/margin
top、left、margin 都会改变元素在文档流中的几何位置,每次变化都强制浏览器重算布局树。而 transform: translateX(20px) 只改图层矩阵,不影响兄弟元素或父容器高度。
真实踩坑场景:模态框入场用 top: 0 → top: 20px,结果下方内容跟着上跳;悬停下划线用 width + display: block,导致整行文字微移。
- ✅ 替代方案:
transform: translateY(-20px)→transform: translateY(0) - ⚠️ 别混搭:
left: -100px+transform: translateX(100px)会导致位移叠加且left仍参与 layout 计算 - ⚠️ 移动端注意:iOS Safari 对小数精度敏感,
translateX(0.001px)可能被忽略,建议用整数或 ≥0.01px 步进
容器要预设尺寸并隔离渲染边界
就算子元素用了 transform,如果父容器没设 overflow: hidden 或 contain: layout,动画溢出仍可能推挤兄弟节点,造成“呼吸感”抖动。
典型问题:图片加载后撑开父容器,导致下方卡片整体下移;表格中某单元格缩放时,整行高度偶发跳变。
- ✅ 给动画容器加
overflow: hidden(如.card、.modal) - ✅ 图片/iframe 必须带
width和height属性,或用padding-top占位(如padding-top: 56.25%实现 16:9) - ✅ FastUI 类框架的动态表单容器,提前设
min-height或用contain: layout锁定渲染范围
用 DevTools 确认是否真修复了 Layout Shift
肉眼觉得“顺”不等于没抖动。Chrome DevTools 的 Layout Shift Regions 功能会用红色高亮残余抖动源,比 FPS 数值更直接可靠。
操作路径:打开 DevTools → Performance 面板 → 录制交互 → 勾选 Layout Shift Regions → 回放动画。看到红色边框跳动?说明仍有 layout 触发点没清理干净。
- ⚠️ 注意:
will-change: transform不是万能开关,滥用会吃内存;只在真正需要持续动画的元素上动态添加,结束后立即移除 - ⚠️
transform: translateZ(0)可强制提升图层,但别全局加——每个额外合成层都增加 GPU 内存开销 - ⚠️ 滚动容器记得加
scrollbar-gutter: stable,避免滚动条出现/消失时左右挤压
transform,而是检查所有相关样式是否彻底剥离了 width、height、margin、padding、border 的隐式变更——它们常藏在伪类、框架默认样式或 JS 动态 class 里。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











