“我加了个过渡动画,怎么页面突然卡了?”
“打开弹窗,动画还没结束,按钮点不了?”
如果你曾在项目中加过 height: 0 → auto 或 left: 0 → 100px 的动画,
你很可能给浏览器带来了不小的负担。
动画如果写得好,叫“顺滑”
如果写得不好,那就是“卡顿的罪魁祸首”。
本篇文章,我们深入探讨:
如何通过合理的属性选择与策略,实现流畅高性能的动画效果。
一、浏览器如何渲染动画?
动画过程的性能瓶颈,通常来自:
-
样式变化触发重排(Reflow)
-
重排后触发重绘(Repaint)
-
帧数下降 → 卡顿
所以问题不在“动画太长”,而是“动了不该动的东西”。
二、好动画要避开的三个坑
动画属性 | 是否影响布局? | 是否会卡? |
---|---|---|
top/left/right/bottom | 会 | 卡 |
width/height/margin/padding | 会 | 卡 |
color/background | 不会 | 有时卡 |
transform/opacity | 不会 | 最优推荐 |
三、性能之王:transform + opacity
这些是浏览器能**硬件加速(GPU 合成)**的属性。
常见 transform 动画:
transform: translateY(20px);
transform: scale(1.05);
transform: rotate(30deg);
示例:淡入上移动效
.modal-enter {
opacity: 0;
transform: translateY(20px);
}
.modal-enter-active {
transition: all 0.3s ease;
opacity: 1;
transform: translateY(0);
}
建议:
-
不要直接 transition top / left
-
优先使用 translate, scale 等组合动画
四、动画优化技巧合集
使用 will-change 提前告知浏览器
.card {
will-change: transform, opacity;
}
注意:不要滥用,因为会提前分配资源,长期使用反而浪费性能。
合理控制 transition 的粒度和 timing
-
不要所有属性都 transition,指定具体项更稳定:
transition: transform 0.3s ease, opacity 0.2s ease;
-
使用 ease-in-out 等缓动函数,减少跳变感
使用 CSS 动画替代 JS 动画(能用 CSS 就别用 JS)
-
CSS 动画由浏览器优化,性能更可控
-
JS 动画更灵活,但主线程压力大(尤其 setInterval、setTimeout)
五、框架实践建议(Vue / React)
Vue 组件动画建议:
-
使用 <transition> 配合类名管理动画
-
v-show 会保留元素,不适合复杂结构的 enter 动画
-
大量元素建议使用 v-memo 或 Teleport 减少干扰
React 动画推荐方式:
-
使用 react-transition-group、framer-motion 实现控制
-
保持每个动画目标单独控制,避免列表动画“全动一起”
六、动画性能调试技巧
使用 Chrome DevTools
-
打开 Performance → 勾选 “Paint” / “Layout Shift” 查看动画细节
-
使用 Layers 面板查看 GPU 合成层(是否 GPU 加速)
使用 prefers-reduced-motion 优化无障碍体验
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
总结:动得漂亮,也得动得轻盈
动画不是不能加,而是要加得聪明:
-
用 transform / opacity
-
控制粒度和触发条件
-
让动画可控、可取消、可被打断
-
别动 height/left/width 来“折磨”浏览器
好动画不应该让用户察觉它存在,但却能感受到它带来的流畅。