用@keyframes bounce定义弹跳关键帧:0% translateY(-30px),50%到0,75%回弹至-10px,100%落定;配合cubic-bezier(0.28, 0.84, 0.42, 1)实现重力回弹感,并设animation-fill-mode: forwards使动画结束停留最终位置。

直接用 CSS 的 @keyframes 配合 animation 就能实现干净利落的弹跳效果,不需要 JS,也不依赖第三方库。
怎么写 bounce 关键帧?
弹跳的核心是模拟重力回弹:先快速下落,再多次幅度递减的反弹。CSS 里用 cubic-bezier() 比用 ease-in-out 更精准——它能控制速度曲线的“弹感”。
-
0.28, 0.84, 0.42, 1是最常用的一组 bounce 曲线值,比默认ease更有物理感 - 如果想更夸张,可试
0.34, 1.56, 0.64, 1(注意第二个值 >1,允许“过冲”) - 关键帧本身只需定义
transform: translateY(),避免触发布局重排(top或margin会)
@keyframes bounce {
0% { transform: translateY(-30px); }
50% { transform: translateY(0); }
75% { transform: translateY(-10px); }
100% { transform: translateY(0); }
}
.element { animation: bounce 0.6s cubic-bezier(0.28, 0.84, 0.42, 1); }
为什么加 animation-fill-mode: forwards?
不加的话,动画播完会瞬间“弹回”初始位置——因为 transform 只在动画期间生效。加了 forwards 才能让元素停在最后一帧的状态(比如落到目标位置)。
- 只对单次播放有效;如果是循环动画(
infinite),forwards无意义 - 若同时用了
transform初始样式(如transform: translateY(-20px)),要确保关键帧起始值和它一致,否则会有跳变 - 别和
animation-direction: alternate混用,容易让终点状态不可控
移动端点按触发弹跳总失效?
常见原因是 Safari 和部分安卓浏览器对未绑定交互事件的元素禁用 :active 状态,导致伪类触发失败。别用 :hover 或 :active 直接触发动画。
立即学习“前端免费学习笔记(深入)”;
- 改用 JS 添加 class 触发:
element.classList.add('is-bouncing'),然后用.is-bouncing { animation: bounce ... } - 确保元素有
cursor: pointer和touch-action: manipulation,减少 iOS 300ms 延迟干扰 - 如果用
click事件,记得加event.preventDefault()防止表单默认行为打断动画流
性能卡顿或闪屏怎么办?
弹跳动画卡顿,90% 是因为触发了重排(layout)或重绘(paint)。重点盯住这三处:
- 绝对别用
width/height/top/left动画——它们强制浏览器每帧计算布局 - 确保元素开启硬件加速:
transform: translateZ(0)或will-change: transform(仅对频繁动画的元素加) - Safari 下
transform: translateY()有时仍闪屏,可补一句backface-visibility: hidden
真正复杂的弹跳逻辑(比如多段不同衰减、碰撞检测)就该交给 JS 库(如 GSAP),CSS 适合轻量、确定性高的反馈动效。



















