弹跳动画需至少4个关键帧(0%、60%、80%、100%)配合cubic-bezier缓动与forwards填充,避免infinite滥用、iOS掉帧及animationend事件失效问题。

用 @keyframes 定义弹跳动画时,关键帧必须包含至少 3 个阶段
纯 CSS 弹跳不是简单上下位移,它需要模拟物理回弹:快速下落 → 触底压缩 → 回弹震荡衰减。只写 0% 和 100% 两帧会变成僵硬抖动,毫无弹性感。
- 典型结构是
0%(起始)、60%(最低点,transform: translateY(50px))、80%(回弹过冲,transform: translateY(-15px))、100%(回归原位) - 必须配合
cubic-bezier(0.28, 0.84, 0.42, 1)这类非线性缓动,系统自带的ease-in-out不够用 - 注意:Y 轴位移值要结合元素自身高度估算,
50px对小图标可能过大,对卡片又可能不够,得实测
animation 属性漏掉 forwards 会导致动画结束后“啪”一下跳回原位
弹跳动画常被用于悬停反馈或加载提示,如果没加 forwards,动画一停,元素立刻重置 transform,视觉上就是突兀的瞬移,完全毁掉弹跳感。
- 正确写法:
animation: bounce 0.6s cubic-bezier(0.28, 0.84, 0.42, 1) forwards; - 别用
infinite直接套在交互动画上——用户鼠标移开后还在跳,体验极差 - 如果需手动触发(比如 JS 控制),记得先清除旧动画:
element.style.animation = 'none';再重设,否则动画可能卡住
移动端 Safari 对 transform: translateY() 的硬件加速支持不稳定
在 iOS 15–16 的部分机型上,仅靠 translateY 做弹跳会出现掉帧甚至直接不执行,尤其叠加其他动画时。
- 临时解法:强制开启 GPU 加速,加一句
transform: translateY(0) translateZ(0);到动画关键帧里 - 更稳妥的做法是改用
top+position: relative,但会触发重排,性能略低,适合低频动画 - 真机测试比 DevTools 模拟器靠谱得多,iOS 模拟器经常骗人
用 JS 控制弹跳节奏时,getComputedStyle 读取 animationName 易踩空
想等弹跳结束再执行下一步(比如显示文案),不能只监听 animationend,因为 Safari 可能不触发,或者多个动画并存时事件乱序。
立即学习“前端免费学习笔记(深入)”;
- 保险做法:用
setTimeout按动画时长 + 50ms 延迟执行后续逻辑,比依赖事件更稳 - 若必须用事件,检查
event.animationName === 'bounce',别只看event.type - 避免在动画进行中反复读取
getComputedStyle(el).transform,这会强制同步布局,卡顿明显
60% 和 80% 的位移值小步试,每次 ±2px,比大改有效。










