真正弹跳需分段贝塞尔曲线模拟物理过程:0%→25%快进慢出下落,25%→50%快出慢进触底回弹,50%→75%小幅二次反弹,75%→100%回稳,配合forwards填充和will-change优化性能。

为什么直接用 transform: translateY() 做不出弹跳感
单纯线性位移(比如从 0 到 -20px 再回 0)看着像上下晃,不是弹跳。真实弹跳有加速度变化:下落快、触底挤压、回弹衰减。CSS 的 @keyframes 本身不支持物理模拟,得靠贝塞尔曲线拟合“弹性”节奏。
- 默认
ease-in-out太匀速,像钟摆,不像弹簧 - 必须用
cubic-bezier(0.28, 0.84, 0.6, 1)这类高弹性值——这是模仿 Material Design 的弹跳缓动 - 单次 keyframe 循环不够,要分段定义:下落 → 触底压缩 → 回弹 → 小幅二次反弹
怎么写一个真正像弹跳的 @keyframes bounce
下面这段是经过实测的「一次完整弹跳」动画,包含 4 个关键帧,用 cubic-bezier 控制每段节奏:
@keyframes bounce {
0% {
transform: translateY(0);
}
25% {
transform: translateY(-30px);
animation-timing-function: cubic-bezier(0.28, 0.84, 0.4, 1);
}
50% {
transform: translateY(0);
animation-timing-function: cubic-bezier(0.72, 0, 0.96, 0.28);
}
75% {
transform: translateY(-10px);
animation-timing-function: cubic-bezier(0.72, 0, 0.96, 0.28);
}
100% {
transform: translateY(0);
}
}
-
25%是下落峰值,位移最大,用「快进慢出」让下落加速、触底前减速(模拟重力+缓冲) -
50%回到原位但立刻接小幅二次上抬(75%),制造弹簧余震感 - 别省略每个
animation-timing-function,它只作用于当前关键帧到下一帧的过渡
图标元素怎么触发这个动画且只加载时执行一次
关键在动画触发时机和复用控制:用 animation 简写属性绑定,并禁用鼠标悬停等干扰行为。
- 给图标加 class,比如
icon--bounce-on-load - 动画名、时长、填充模式、延迟、迭代次数都要显式声明:
animation: bounce 0.8s ease-out forwards; -
forwards防止动画结束后图标跳回初始位置 - 用
animation-delay: 0.2s可错开多个图标入场,避免同时抖动 - 不要用
animation-iteration-count: infinite,否则会一直弹——除非你真想要魔性效果
示例样式:
立即学习“前端免费学习笔记(深入)”;
.icon--bounce-on-load {
display: inline-block;
animation: bounce 0.8s cubic-bezier(0.28, 0.84, 0.6, 1) forwards;
}
容易被忽略的兼容性和性能坑
移动端 Safari 和旧版 Android WebView 对 transform + keyframes 组合有渲染毛刺,尤其在低配设备上。
- 务必加
will-change: transform提前告知浏览器该元素将动画,触发 GPU 加速 - 避免同时对
top/left和transform动画——会强制重排,卡顿明显 - IE11 不支持
cubic-bezier()在@keyframes内使用,如果还要兼容,得降级为ease-out并缩短动画时长(0.5s) - 图标本身要是
inline或inline-block,否则transform可能失效(block 元素需明确宽高或触发 BFC)
最终上线前,在真机上快速滚动页面,看图标是否偶发闪烁或位移偏移——那是硬件加速未生效的信号。










