抖动动画应使用@keyframes定义并配合animation-fill-mode:forwards,至少4–5帧、时长0.3s–0.5s、结尾归零,JS触发需强制重排防卡顿,移动端需加translateZ(0)启用硬件加速。

抖动动画用 @keyframes 定义,别用 transform: translate() 硬写
CSS 抖动本质是快速左右/上下位移,靠 @keyframes 控制关键帧最稳妥。手写一串 transform: translateX(2px) → translateX(-2px) 不仅难维护,还容易漏掉回弹或时序错乱。
常见错误是只写两个状态(比如 0% 和 100%),结果动画“卡”一下就结束,没有震动感。真正有效的抖动至少需要 4–5 帧,让视觉有加速、减速、回弹的节奏感。
- 推荐起始帧设为
transform: translateX(0),避免初始偏移 - 中间帧用 ±2px ~ ±4px 范围,超过 ±6px 易触发用户不适
- 结尾帧必须回到
translateX(0),否则元素会留在偏移位置
@keyframes shake {
0% { transform: translateX(0); }
25% { transform: translateX(-3px); }
50% { transform: translateX(2px); }
75% { transform: translateX(-2px); }
100% { transform: translateX(0); }
}
触发抖动要用 animation,但别忘了加 animation-fill-mode: forwards
抖动通常是交互反馈(比如表单校验失败),不是持续循环。直接写 animation: shake 0.4s 会导致动画播完立刻跳回原始位置——肉眼可见“抽搐一下又弹回去”,体验极差。
根本原因是 CSS 动画默认不保留最终状态。必须显式加上 animation-fill-mode: forwards,让最后一帧样式生效并停留。
立即学习“前端免费学习笔记(深入)”;
- 时间控制在 0.3s–0.5s 之间:短于 0.2s 感觉不到,长于 0.6s 显得拖沓
- 别用
infinite,除非你真要模拟地震(一般不需要) - 如果同时有多个抖动元素,避免全部同步触发,可加
animation-delay错开 0.05s
示例:animation: shake 0.4s ease-in-out forwards;
抖动类名要可复用,但得防重复触发导致动画卡顿
给元素加抖动类(比如 .shake)很常见,但如果用户连续点击多次,类名反复增删,animation 可能因样式重绘未完成而卡住,甚至出现“越抖越慢”或“停在半路”。
核心解法是确保每次触发前先移除类,再强制重排(reflow),再加回类。纯 CSS 无法解决,必须配合 JS。
- 不要用
element.classList.add('shake')单步操作 - 正确做法:
element.classList.remove('shake');→void element.offsetWidth;(触发重排)→element.classList.add('shake') - 更稳妥的做法是用
animationend事件清理类名,避免手动管理时机
移动端要注意 transform 硬件加速和 Safari 兼容性
抖动动画在 iOS Safari 上容易掉帧,尤其老机型。根本原因是 translateX 在某些 Safari 版本中未自动启用 GPU 加速,得手动“骗”一下。
加 transform: translateZ(0) 或 will-change: transform 是常用手段,但后者慎用——它会持续占用图层资源,抖动结束后务必清除。
- 推荐写法:
transform: translateX(0) translateZ(0),既兼容又轻量 - Safari 15.4+ 支持
animation-timeline: view(),但抖动场景完全用不上,别凑热闹 - 真遇到 iOS 抖不动,先检查是否父容器有
overflow: hidden截断了动画渲染区域


















