css3动画不卡顿的关键是只用transform和opacity属性,加will-change优化,避免重排;js动画用requestanimationframe对齐刷新率;transition与animation勿混用;移动端需在touch事件中启动并启用gpu加速。

CSS3 animation 怎么写才不卡顿
直接用 animation 写动画,90% 的卡顿来自属性选择错误。浏览器只能高效渲染 transform 和 opacity,改 left、top 或 width 会强制触发重排(reflow),尤其在中低端设备上掉帧明显。
实操建议:
- 动画属性只用
transform: translateX()、transform: scale()、opacity,别碰margin、padding、height - 加
will-change: transform提前告知浏览器要动,但别滥用——只加在真正要动画的元素上,否则内存开销变大 - 时间函数别全用
ease,滚动类动画建议ease-out,交互反馈类用ease-in,避免突兀感 - 示例:
div { animation: slideIn 0.3s ease-out; }<br>@keyframes slideIn {<br> from { opacity: 0; transform: translateX(-20px); }<br> to { opacity: 1; transform: translateX(0); }<br>}
requestAnimationFrame 什么时候必须用 JS 动画
当动画逻辑依赖运行时数据(比如鼠标位置、滚动进度、Canvas 绘图节奏),CSS 动画就扛不住了。requestAnimationFrame 是唯一能跟屏幕刷新率对齐的 JS 方案,比 setTimeout 稳定得多。
常见错误现象:
立即学习“前端免费学习笔记(深入)”;
- 用
setInterval控制动画帧,结果在高刷屏或后台标签页里节奏错乱 - 在
raf回调里反复读取offsetTop或getBoundingClientRect(),导致强制同步布局(layout thrashing) - 没做 cancel —— 页面卸载后回调还在执行,引发内存泄漏
- 示例:
let animationId;<br>function animate() {<br> // 更新状态<br> element.style.transform = `translateX(${x}px)`;<br> if (stillAnimating) animationId = requestAnimationFrame(animate);<br>}<br>animate();<br>// 卸载前记得:<br>cancelAnimationFrame(animationId);
transition 和 animation 混用容易踩什么坑
两者底层机制不同:transition 是状态驱动(从 A 到 B),animation 是时间轴驱动(关键帧序列)。混用时最常出问题的是“覆盖失效”和“意外中断”。
使用场景判断:
- 按钮悬停变色、卡片展开收缩 → 用
transition更轻量,声明式简单 - 加载骨架屏、路径描边、复杂入场动效 → 必须用
@keyframes + animation - 如果同时写了
transition: all和animation,动画期间transition会被忽略;动画结束后,若属性值又变了,transition才重新生效 - 想让动画结束后保持最终状态?必须加
animation-fill-mode: forwards,否则瞬间回退到初始值
移动端 touch 事件里启动 CSS 动画为什么没反应
因为 iOS Safari 和部分安卓 WebView 在非用户手势触发的 JS 上,会禁用硬件加速动画(即 transform 不走 GPU)。哪怕你写了 transform,也可能降级成软件渲染,肉眼可见卡顿甚至不动。
解决办法很具体:
- 确保动画启动发生在
touchstart或touchend回调内(不能是异步延时后的回调) - 给动画元素加
transform: translateZ(0)或will-change: transform强制启用 GPU 层 - 避免在
touchmove里频繁修改style.transform—— 改用requestAnimationFrame节流,否则触控响应延迟明显 - 真遇到动画不触发,先检查是否被
pointer-events: none或visibility: hidden意外拦截了










