transition-all 危险在于全量监听可动画属性,会意外触发 width、height 等重排属性及 box-shadow、filter 等高开销重绘,导致卡顿、掉帧甚至归零重播;应显式限定为 transition-transform opacity 等 GPU 加速属性。

transition-all 会监听所有可动画属性,包括触发重排的 width 和 height
浏览器对 transition-all 的实现是“全量监听”——只要某个属性支持 CSS 动画(哪怕你根本没动它),它就会被纳入过渡系统。而 width、height、margin、left、top 这类属性一旦变化,必须同步计算布局(reflow),直接拖慢帧率。更麻烦的是,这些属性常被 JS 意外修改(比如 resize 触发、flex 布局重算、甚至某些库的 DOM 操作),导致过渡被反复触发。
悬停或状态切换时,box-shadow、filter 等高开销属性也被强制过渡
当你只希望按钮缩放 + 变色,但写了 transition-all,浏览器还会对 box-shadow、filter、text-shadow 等属性做插值运算。这些属性属于“绘制层”(paint),每次重绘都涉及像素级计算,尤其在低端设备或密集列表中,很容易掉帧。
- Chrome DevTools 的「Rendering」面板开启「Paint flashing」后,能看到大面积黄色闪烁 —— 那就是
box-shadow或filter在反复重绘 - 如果同时加了
will-change: transform,但transition-all仍监听padding,图层缓存会被破坏,反而比不用will-change更慢
React/Vue 中 JS 更新样式时,transition-all 容易引发“归零重播”
比如步进器进度条从第 1 步跳到第 4 步,若用 width + transition-all,浏览器不会记住上一帧的渲染宽度,而是回退到声明的初始值(如 width: 0%)再开始动画,造成明显跳变。这不是 Tailwind 的 bug,而是 CSS 过渡机制本身的限制。
- 正确做法是:用
transform: scaleX()替代width,因为它不依赖布局,且缩放始终基于元素原始尺寸 - JS 控制时,先读
getComputedStyle(el).width获取当前值,再设目标值,避免重置 - Tailwind v4+ 推荐组合:
transition-transform duration-300 ease-in-out+hover:scale-105
真正危险的不是写错,而是把性能决策权交给了浏览器
transition-all 看似省事,实则放弃控制权。浏览器面对所有可动画属性,会选择最保守(也最慢)的路径:升层 → 监听 → 重排/重绘 → 插值 → 合成。而明确写 transition-transform opacity,等于告诉浏览器:“只管 GPU 加速那两件事,别的别碰”。
立即学习“前端免费学习笔记(深入)”;
容易被忽略的一点是:duration- 类(如 duration-300)必须和 transition- 类共存于基础元素上;如果只挂在 hover: 后面,鼠标移出时动画会直接跳回,根本看不出过渡效果。


















