transition: all 在 Less 中危险,因绕过硬件加速、引发重排重绘、导致动画卡顿或失效,且 Autoprefixer 易漏前缀;应改用参数化 Mixin 显式控制可动画属性。

直接在 Less 里写 transition: all 0.3s 看似省事,但大概率导致卡顿、闪烁或动画不触发——这不是写法错,而是它绕过了浏览器对可动画属性的硬件加速机制,也掩盖了真实性能瓶颈。
为什么 transition: all 在 Less 中特别危险
Less 编译器不会合并重复的 transition 声明。如果你在基态写了 transition: all 0.3s,又在 &:hover 里改了 background-color 和 transform,浏览器实际只执行最后一条声明,且 all 会强制让所有变化属性(包括 height、margin、font-size)参与过渡,引发重排(reflow)和重绘(repaint)。
- 常见错误现象:
.card:hover动画“跳一下”再开始,或低端安卓 WebView 中完全无响应 - 真正可被 GPU 加速的只有
transform、opacity、filter(部分)——其余都走主线程 - Less 中写
all还会导致 Autoprefixer 漏补前缀,比如 IE11 下-ms-transition不生效
用参数化 Mixin 显式控制可动画属性
把过渡逻辑封装成带默认值的 Mixin,调用时必须显式传入要动的属性,既防误用,也便于后期统一调整时长或缓动函数。
.transition(@prop: transform, @dur: 0.25s, @easing: cubic-bezier(0.25, 0.46, 0.45, 0.94)) {
-ms-transition: ~"@{prop} @{dur} @{easing}";
-webkit-transition: ~"@{prop} @{dur} @{easing}";
transition: ~"@{prop} @{dur} @{easing}";
}
- 调用示例:
.transition(transform, 0.3s)或.transition(opacity, 0.2s, ease-in) - 多个属性需不同持续时间?拆开写两行:
.transition(transform, 0.3s); .transition(opacity, 0.15s);,不要塞进一个 Mixin - 避免在 Mixin 内部硬编码
will-change——它开销大,应由组件自己决定是否加:will-change: transform;
配合 transform 和 will-change 实现零重排动画
导航栏下拉、卡片悬停这类效果,必须放弃 height 或 display,改用 transform: scaleY(0) + opacity: 0 控制显隐,并在基态加 will-change: transform 提前提示浏览器。
立即学习“前端免费学习笔记(深入)”;
-
transform和opacity是唯二能稳定触发合成层(compositing layer)的属性,动画帧率才稳 -
will-change必须写在初始状态(非&:hover),否则提示太晚,第一帧就掉帧 - 慎用
backface-visibility: hidden:它虽防字体模糊,但在某些 Android Webview 中反而引发闪烁,仅在含文字的transform动画中启用
嵌套层级与选择器性能的隐形代价
Less 嵌套本身不慢,但编译后生成的后代选择器(如 .nav .dropdown .menu-item)会让浏览器匹配变慢——尤其当 DOM 深度 >3 层时,样式计算耗时上升超 40%。
- 错误写法:
.dropdown { & .menu-item { .transition(transform); } }→ 输出.dropdown .menu-item,低效 - 正确写法:
.dropdown-menu-item { .transition(transform); },用 BEM 类名替代嵌套推导 - 媒体查询别塞进嵌套里:
@media (max-width: 768px) { .nav { ... } }应提至顶层,避免重复输出父链
最易被忽略的一点:transition 的兼容性兜底不是靠 Autoprefixer 全包,而是 Mixin 内显式写 -ms-transition 和 -webkit-transition;只要还有 1% 用户跑 IE11 或旧版 Safari,漏掉这一行,动画就彻底静止——它不会报错,只会沉默失效。



















