左右摇晃动画需用至少4帧实现“停→右→停→左→停”节奏,位移±8px、时长0.4s、缓动cubic-bezier(.36,.07,.19,.97),配合animation-fill-mode:forwards和transform:translatez(0)确保效果精准可信。

用 @keyframes 定义左右摇晃动画时的关键帧偏移量
抖动效果本质是水平位移的快速往复,不能只靠 transform: translateX() 简单来回——浏览器会优化掉微小位移或合并过渡,导致动画卡顿或不触发。必须用至少 4 个关键帧形成“停→右→停→左→停”的节奏,让视觉感知到“被拒绝”的反馈感。
常见错误是写成只有 0% 和 100% 两帧,或者用 50% 做对称偏移(比如 ±10px),这样容易变成平滑晃动而非“生硬抖动”。正确做法是让中间帧停留时间极短、且偏移方向突变:
@keyframes shake {
0% { transform: translateX(0); }
25% { transform: translateX(-8px); }
50% { transform: translateX(0); }
75% { transform: translateX(8px); }
100% { transform: translateX(0); }
}
其中 -8px 和 8px 是经验值:小于 5px 不明显,大于 12px 易引发不适;25% 和 75% 帧不设停留,靠动画缓动函数控制瞬时感。
给输入框添加抖动类时要避开 :focus 干扰
表单验证通常在用户失焦(blur)或提交时触发,但若此时输入框仍处于聚焦状态,直接加抖动类可能被 :focus 样式覆盖(比如 outline 或 box-shadow),导致抖动不可见。
实操建议:
- 抖动类(如
.shake)的 CSS 权重需高于:focus规则,例如写成input.shake:focus或直接用!important(仅限此场景) - 抖动触发后,用 JS 在动画结束时自动移除类,避免连续点击重复绑定动画事件:
element.addEventListener('animationend', () => element.classList.remove('shake')) - 不要在
:focus状态下主动触发抖动——人正在输入,抖动会干扰操作,应等用户明确提交或离开该字段后再反馈
animation 属性里必须显式指定 animation-fill-mode: forwards
否则动画播完立刻回退到初始状态,用户只看到“一闪”,无法确认错误已发生。尤其当抖动用于登录失败后的整体表单反馈时,这个细节决定体验是否可信。
完整声明示例:
.shake {
animation: shake 0.4s cubic-bezier(.36,.07,.19,.97) both;
}
注意三点:
-
cubic-bezier(.36,.07,.19,.97)是“先快后猛停”的缓动,比默认ease更有冲击力 -
both是animation-fill-mode: forwards的简写,确保最后一帧样式保留 - 持续时间
0.4s是临界值:短于 0.3s 感觉像闪屏,长于 0.6s 显得拖沓,且易和后续错误提示(如文字红字)不同步
移动端 Safari 对 transform 动画的兼容处理
iOS 15 之前,Safari 对 translateX 在表单控件上的硬件加速支持不稳定,尤其配合 border 或 outline 时可能出现抖动错位或闪烁。
绕过方案:
- 给抖动元素加
transform: translateZ(0)强制开启 GPU 加速(写在.shake类里) - 避免在
input[type="password"]上直接应用抖动——iOS 键盘弹起时布局重排易导致动画中断,改为对父div容器加抖动类更稳妥 - 测试真机:模拟器常表现正常,但 iPhone 实际触控后
blur事件延迟可能导致抖动滞后,建议加 50ms 防抖再触发动画
抖动不是炫技,而是把“你输错了”这件事用肌肉记忆的方式钉进用户意识里——所以位移量、时长、触发时机,每个数字都得抠到像素级。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











