用CSS animation实现点击震动需定义shake关键帧动画,点击后JS动态添加is-shaking类并监听animationend事件自动移除,配合节流避免连点错乱,兼顾兼容性与真实机型测试。

用 CSS animation 实现点击后按钮震动,不依赖 JS
震动效果本质是短时位移+旋转的组合动画,纯 CSS 就能完成。关键不是“点击触发”,而是“点击后临时加 class”,否则无法用 :active 模拟(因为 :active 持续时间太短,人眼几乎看不到震动)。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 定义一个
@keyframes shake,推荐 6–8 帧,x 方向偏移 ±4px,可加轻微 rotate(-1deg) → rotate(1deg),总时长控制在 0.4s 内 - 给按钮添加
.btn-add-to-cart类,并默认不启用动画;点击后 JS 动态加is-shaking类,动画结束后自动移除(避免重复点击卡顿) - 不要用
transform: translateX()配合transition做“来回切”,那样容易因浏览器重排导致抖动不连贯
Element.classList.toggle() + animationend 事件确保只播一次
直接写 element.classList.add('is-shaking') 然后立刻 remove 是错的——动画还没开始就被删了。必须等动画真正结束再清理 class。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 绑定
animationend事件监听器,检查e.animationName === 'shake'再执行remove - 使用
element.addEventListener('animationend', handler, { once: true }),自动解绑,避免内存泄漏 - 如果用户快速连点,需加节流:比如 500ms 内禁止重复触发震动(否则多个
is-shaking叠加,动画会错乱)
震动太强或太弱?调这 3 个 CSS 参数就够了
实际项目中常见问题不是不会写,而是震得像地震,或者轻得像没反应。核心就三个可控变量:
-
animation-duration:0.3s~0.5s 最自然,小于 0.2s 显突兀,大于 0.6s 显拖沓 -
transform: translateX()偏移量:±2px~±6px 之间,移动端建议 ≤4px,桌面端可到 ±6px -
animation-timing-function:别用ease或linear,改用cubic-bezier(0.36, 0.07, 0.19, 0.97)(类似 iOS 弹性回弹),震动更有“肉感”
`.btn-add-to-cart.is-shaking {
animation: shake 0.4s cubic-bezier(0.36, 0.07, 0.19, 0.97);
}
@keyframes shake {
0% { transform: translateX(0); }
25% { transform: translateX(-4px); }
50% { transform: translateX(4px); }
75% { transform: translateX(-2px); }
100% { transform: translateX(0); }
}`
兼容性注意:transform 和 animation 在旧 Android WebView 里可能失效
Android 4.4 及更早版本的系统 WebView 对 transform 的硬件加速支持不稳定,可能出现闪烁、卡顿甚至完全不动。这不是代码问题,是渲染引擎限制。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 检测 UA 中是否含
Android 4.且WebView,如果是,降级为仅用opacity微闪(animation: fade 0.3s) - 不要给震动元素设
position: absolute或z-index过高,某些低端机上会触发层叠上下文异常,导致震动偏移错位 - 真机测试务必覆盖 Android 5.0~6.0 的主流机型(如红米 Note 3、华为 P8),模拟器往往测不出问题
animationend 就手动删 class,结果后续点击完全没反应。先保逻辑健壮,再调震感。



















