纯CSS重力弹跳需用cubic-bezier非线性缓动模拟加速度,单keyframes定义完整周期(下落+压缩+反弹+衰减),配合scale形变、固定容器高度、absolute定位与overflow:hidden裁剪,分段设置timing-function及top值实现真实物理感。

用 transform + keyframes 模拟重力加速度效果
纯 CSS 无法真正计算物理公式,但可以通过非线性贝塞尔缓动(cubic-bezier(0.34, 1.56, 0.64, 1))逼近下落加速、触底压缩、反弹减速的过程。关键不是“匀速上下”,而是让动画曲线在触底前后有明显速度变化——顶部慢→中段快→底部骤停→反弹初速高→越弹越慢。
常见错误是直接用 ease-in-out:它对称,导致反弹高度不变,完全不像真实弹跳;或者用多个 animation 叠加,结果时间难对齐、状态不可控。
- 推荐单个
@keyframes描述完整一次弹跳周期(含下落 + 反弹 + 暂停),再用animation-iteration-count: infinite循环 - 触底瞬间加入
transform: scale(0.85, 0.5)模拟形变,增强物理感 - 每次反弹高度递减,需手动设多段
keyframes的top值(如0%→100%对应0→80%,100%→200%对应80%→45%)
边界检测必须靠父容器 overflow: hidden 配合绝对定位
CSS 动画本身不提供“碰撞检测”,所谓“在指定边界内”全靠视觉裁剪+位置约束。小球元素必须设 position: absolute,其父容器设 position: relative 和 overflow: hidden,否则小球会跳出容器、甚至拖出滚动条。
容易被忽略的是:动画中 top 值若设为百分比(如 top: 100%),实际是相对于父容器高度,但触底位置要精确到像素才好控制反弹起点。所以更稳妥的做法是用 vh 单位或固定像素值,并确保父容器高度明确(不能是 min-height 或内容撑开)。
- 父容器高度建议写死,例如
height: 400px,避免因内容变动导致边界漂移 - 小球宽高需远小于容器,否则
scale形变时可能撑破边界 - 不要依赖
bottom: 0触底——它和top冲突,且动画中top优先级更高
用 animation-timing-function 分段控制每段运动节奏
一次弹跳包含下落、触底压缩、主反弹、二次微弹四个阶段,全部塞进一个 cubic-bezier 几乎不可能。正确做法是把整个动画拆成多个连续时间段,每段用不同缓动函数:
0%, 50% { top: 0; animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1); }
50%, 70% { top: 80%; animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1); }
70%, 90% { top: 45%; animation-timing-function: cubic-bezier(0.33, 0.01, 0.54, 1); }
90%, 100% { top: 20%; }
注意:这些时间点(50%、70%…)不是等分的,要根据物理衰减规律调整——前两次反弹间隔短、幅度大,后面越来越稀疏。若用 JS 控制会更灵活,但纯 CSS 下只能靠反复调试时间轴和 top 值。
-
cubic-bezier第二个参数 > 1 表示“加速超调”,是实现重力感的关键,但部分旧版 Safari 不支持,需加-webkit-前缀 - 别用
steps(),它会导致跳跃式移动,彻底失去加速度效果 - 动画总时长建议设为
1.8s左右,太短显得急促,太长失去弹跳张力
移动端需额外处理 will-change 和缩放适配
在 iOS Safari 或安卓 Chrome 上,快速位移的小球容易出现闪烁或掉帧,尤其叠加 scale 形变时。根本原因是浏览器没提前启用 GPU 加速。
解决方案不是盲目加 transform: translateZ(0),而是精准触发:只在动画进行中启用 will-change: transform,动画暂停时移除(否则持续占用 GPU 内存)。可通过 class 切换模拟,或用 @keyframes 中嵌入 will-change(但兼容性较差)。
- 真机测试时,务必关掉“减少动画”系统设置,否则所有
animation会被强制降级为淡入淡出 - 如果页面允许缩放(
viewport未禁用),用户双指放大后,vh单位会失准,建议边界容器用固定像素 - 小球
border-radius: 50%在低分辨率屏上可能显锯齿,可加transform: translateZ(0)强制抗锯齿
重力弹跳看着简单,难点全在曲线拟合和边界容错——哪怕时间轴偏移 5%,反弹节奏就全乱了。动手前先用 DevTools 的动画审查器逐帧拖动,比写十遍代码都管用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











