transition: all 是性能地雷,会导致 Safari 和 Firefox 掉帧、卡顿甚至动画失效,因其强制检查所有可动画属性并触发重排重绘;应显式声明 transform 和 opacity 等低开销属性。

transition: all 不是懒人写法,是性能地雷。它会让 Safari 和 Firefox 在 hover、class 切换等常见场景下掉帧、卡顿,甚至动画直接不触发——不是代码没跑,是浏览器主动跳过了整条规则。
为什么 transition: all 会卡顿甚至失效
浏览器看到 all,就默认你要过渡所有可动画属性:哪怕你只改了 opacity,它仍得检查 width、margin、background-color 是否有变。这些属性一动就触发重排(reflow)或重绘(repaint),主线程立刻吃紧。
- Safari 对
all特别敏感,轻微布局扰动(比如父容器尺寸抖动)就导致合成层降级 - Firefox 更保守:如果初始状态含
display: none或visibility: hidden,它可能直接忽略整个transition声明,DevTools Animations 面板里连时间轴都看不到 -
all还会隐式包含top、left、height等高开销属性,哪怕你当前 CSS 里根本没写它们
哪些属性可以放心加进 transition
真正走 GPU 合成层、不触发布局和绘制的,只有两个核心属性:transform 和 opacity。其他所谓“安全”属性都带条件。
-
transform:包括translateX、scale、rotate等,必须是完整函数值(如translateY(20px)),不能只写translate -
opacity:纯透明度变化,零重排零重绘 -
background-color、color:仅影响 paint 阶段,比 layout 轻,但旧版 Safari 中仍可能走主线程 -
box-shadow:现代 Chrome/Firefox 可合成,但需配合will-change: transform或提前升层,否则易掉帧
绝对不要单独写:transition: width 0.3s、transition: margin 0.3s、transition: left 0.3s——它们强制同步计算布局,滚动时帧率肉眼可见下跌。
立即学习“前端免费学习笔记(深入)”;
如何快速定位并替换残留的 transition: all
别靠肉眼翻 CSS 文件。打开 DevTools Elements 面板,用 Cmd+F(Mac)或 Ctrl+F(Win)全局搜 transition: all 和 transition-property: all;重点检查 :hover、.active、.open、.is-visible 这类动态类。
- 运行这段脚本快速扫描:
Array.from(document.querySelectorAll('*')).filter(el => getComputedStyle(el).transitionProperty === 'all').forEach(el => console.warn('All transition found:', el)) - Animate.css 用户注意:某些定制 build 默认启用了
all,建议查node_modules/animate.css/animate.min.css里是否含该字符串 - 替换时别写成
transition: transform, opacity—— 缺少时长和缓动,浏览器按默认0s ease处理,等于没过渡;正确写法是transition: transform 0.3s ease, opacity 0.3s ease
用 will-change 或 translateZ(0) 前先确认必要性
加 will-change: transform 并不能挽救 transition: all 的问题,反而可能更糟:一旦 JS 后续改了 padding 或 font-size,图层缓存被破坏,触发回流 + 重绘 + 图层重建三连击。
-
will-change应只在交互前临时添加(比如mouseenter时 setAttribute),动画结束立即移除 -
translateZ(0)是更稳妥的升层方式,但只对已含transform的元素有效;纯opacity动画需额外加will-change: opacity(Chrome 支持,Firefox 不推荐) - 真正省资源的做法,是删掉一个
all,而不是加十个will-change
最常被忽略的一点:性能瓶颈从来不在“有没有动画”,而在“浏览器有没有被逼着反复做 layout 和 paint”。显式声明属性不是为了代码好看,是给渲染引擎一条清晰的执行路径——它知道只盯哪几个值,就能把其余计算全甩给 GPU。



















