CSS 动画可以让页面更有层次感,比如按钮过渡、菜单展开、弹窗出现、卡片悬停、加载提示等。但动画写得不好,也会带来卡顿、掉帧、耗电和交互延迟。性能优化的关键,是理解哪些属性适合动画,哪些属性会触发布局和重绘。
本文从 transition 和 animation 的区别讲起,再介绍浏览器渲染流程、GPU 加速、常见卡顿原因和实践建议,帮助你写出更顺滑也更可维护的 CSS 动画。
transition 适合状态变化
transition 适合处理两个状态之间的过渡,比如按钮 hover、输入框聚焦、菜单展开、卡片悬停等。它不需要定义关键帧,只要指定哪些属性需要过渡。
.button {
background: #1677ff;
transition: background 0.2s ease, transform 0.2s ease;
}
.button:hover {
background: #0958d9;
transform: translateY(-2px);
}
如果动画只是从默认状态变到另一个状态,优先考虑 transition。它简单、直观,也更容易维护。
animation 适合连续动画
animation 适合更复杂或连续的动画,比如加载旋转、呼吸灯、骨架屏闪动、循环提示等。它通过 @keyframes 定义多个阶段。
.spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
如果动画需要循环、分阶段、自动播放,使用 animation 更合适。不要为了简单 hover 效果写复杂关键帧。

渲染流程
浏览器渲染页面大致会经历样式计算、布局、绘制和合成。不同 CSS 属性变化,会触发不同成本的工作。影响布局的属性通常更容易卡顿。
比如修改 width、height、top、left、margin,可能触发布局计算;修改颜色、阴影可能触发绘制;修改 transform 和 opacity 通常更容易走合成层,性能更好。
优先 transform
移动、缩放、旋转这类动画,尽量使用 transform,而不是修改 top、left 或宽高。
.panel {
transform: translateX(0);
transition: transform 0.3s ease;
}
.panel.is-open {
transform: translateX(100%);
}
同样是移动元素,transform 通常比改变定位值更流畅。尤其是移动端设备上,这个差异会更明显。
优先 opacity
淡入淡出动画优先使用 opacity。如果同时需要隐藏元素和避免点击,可以配合 visibility 或在动画结束后切换状态。
.modal {
opacity: 0;
transition: opacity 0.2s ease;
}
.modal.is-open {
opacity: 1;
}
不要用频繁改变高度或 display 来做简单淡入淡出。display 本身不能平滑过渡,通常需要结合其他属性处理。
GPU 加速
很多文章会提到 GPU 加速。实际开发中,不要盲目给所有元素加 translateZ(0) 或 will-change。这些做法可能创建额外合成层,占用更多内存。
.card:hover {
will-change: transform;
}
will-change 适合少量、确实即将发生动画的元素。动画结束后如果长期不需要,可以移除或避免一直声明。它是性能提示,不是万能加速开关。
避免昂贵属性
阴影、滤镜、模糊、大面积渐变等效果在动画中可能成本较高。比如频繁动画 box-shadow 或 filter: blur(),在低端设备上很容易掉帧。
.bad {
transition: box-shadow 0.3s ease;
}
如果确实需要阴影变化,可以减少变化范围,或者用伪元素和透明度模拟部分效果。动画越大、越频繁,越要谨慎。
控制动画范围
动画元素越多、面积越大,性能压力越明显。列表里几十个卡片同时动画、整屏背景持续变化、多个大图滤镜同时运行,都可能导致页面卡顿。
实际项目中,动画应该服务交互反馈,而不是抢用户注意力。按钮、弹窗、菜单、加载状态用少量动画即可,不要让整个页面一直动。
尊重用户偏好
部分用户对动画敏感,系统可能开启“减少动态效果”。CSS 可以使用 prefers-reduced-motion 媒体查询,减少或关闭非必要动画。
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms;
animation-iteration-count: 1;
transition-duration: 0.01ms;
}
}
这不仅是无障碍优化,也能让页面对更多用户更友好。对关键业务页面来说,动画永远不应该阻碍用户完成任务。
调试工具
浏览器开发者工具可以帮助排查动画性能问题。Performance 面板能看到掉帧和长任务,Rendering 面板可以显示重绘区域,Layers 面板能观察合成层。
调试时不要只在高性能电脑上看效果,也要考虑普通手机和低端设备。动画在开发机上流畅,不代表真实用户设备上也流畅。
常见错误
第一种错误是用 top、left 做移动动画。第二种错误是给大量元素长期设置 will-change。第三种错误是动画阴影、模糊等昂贵属性。第四种错误是动画太多,影响用户阅读和点击。
还有一种错误是忽略动画结束状态,导致元素视觉上隐藏了,但仍然挡住点击区域。弹窗、抽屉和下拉菜单尤其要注意交互状态与视觉状态一致。
实践建议
写 CSS 动画时,可以按这个顺序判断:简单状态变化用 transition;连续或多阶段动画用 animation;移动和缩放优先用 transform;淡入淡出优先用 opacity;少用大面积阴影和滤镜;只在必要时使用 will-change。
好的动画应该轻、快、明确。它帮助用户理解界面变化,而不是制造额外负担。性能优化不是完全不用动画,而是让动画在正确的位置、用正确的属性、以合适的节奏出现。














暂无评论内容