cubic-bezier 本身不能模拟真实物理弹跳,它只是控制动画节奏的数学工具;真正产生弹跳感需关键帧状态设计、超出[0,1]的y值控制点及多段缩放/位移耦合。

直接说结论:cubic-bezier 本身不能“模拟真实物理弹跳”,它只是控制动画节奏的数学工具;真正产生弹跳感,靠的是**关键帧状态设计 + 超出 [0,1] 的 y 值控制点 + 多段缩放/位移耦合**。浏览器对 y 值越界的支持并不统一,盲目套用高弹值反而会静默降级为 ease。
为什么cubic-bezier(0.34, 1.56, 0.64, 1)看起来像弹跳,但实际不总生效
这个值在 Chrome 和 Firefox 中能触发“超调”(即动画冲过目标值再回调),形成回弹视觉;但在 Safari 中,y1 = 1.56 会被静默忽略,整条曲线退化为默认 ease,结果就是软塌塌地落下去、没反弹。这不是 bug,是规范允许的实现差异。
- 必须验证:打开 Chrome DevTools → Animations 面板 → 点击时间函数预览图,如果显示为直线而非曲线,说明 y 值越界失效
- 安全替代方案:改用
cubic-bezier(0.28, 0.84, 0.43, 1.25)—— y2=1.25 在多数环境仍有效,且回弹幅度可控,不易晃眼 - 别依赖单个贝塞尔值“包打天下”:下落、触底、反弹、衰减四个阶段应使用不同缓动,靠 @keyframes 分段定义,而不是指望一个
cubic-bezier()搞定全部
@keyframes里怎么写才能让球“压扁再弹起”
只写 transform: translateY() 永远只是上下飘,不是弹跳。必须把位移、垂直缩放、微旋转三者绑在同一关键帧上,并让它们节奏错开:
- 0% → 50%:下落 + 触底压缩 →
transform: translateY(200px) scaleY(0.7) rotateZ(2deg) - 50% → 70%:快速反弹 →
transform: translateY(140px) scaleY(1.15)(此处用cubic-bezier(0.34, 1.56, 0.64, 1)) - 70% → 100%:二次小幅反弹 + 回稳 →
transform: translateY(175px) scaleY(0.95)→translateY(180px) scaleY(1) - 务必加
animation-fill-mode: forwards,否则动画结束瞬间缩放会归零
transition中用cubic-bezier做悬停弹跳,为什么按钮一 hover 就猛冲
常见错误是把强弹值直接塞进 transition,比如:transition: transform 0.6s cubic-bezier(0.68, -0.6, 0.32, 1.6)。y1=-0.6 在 Safari 和部分安卓 WebView 中直接失效,导致前半段变成线性加速,视觉上就是“突然炸开”。
- 更稳妥写法:
transition: transform 0.6s cubic-bezier(0.4, 0.1, 0.3, 1.3)—— y2=1.3 够弹但不过激,x1/x2 控制启动柔和 - 必须限制作用域:只对
transform做 transition,别混入color或background,否则缓动函数会被浏览器按属性分别计算,节奏错乱 - 移动端慎用:手指悬停无明确起点,容易误触发;建议加
@media (hover: hover)条件包裹
max-height做下拉菜单弹性动画,为什么回弹发虚
因为 max-height 动画本质是数值插值,若设 max-height: 9999px,浏览器要在极大跨度内应用 cubic-bezier,末尾微小变化被稀释,回弹感就弱了。
- 正确估算方式:
max-height: calc(1.5em * 6 + 1.5rem)(按最多 6 行文字 + 内边距) -
transform-origin: top center必须显式声明,否则scaleY()从中心缩放,菜单像被“撕开”而不是从顶部展开 - 记得配
overflow: hidden,否则过冲阶段内容会短暂溢出容器边缘
真正难的不是调出那个“弹一下”的曲线,而是判断什么时候该用缩放、什么时候该压低透明度、哪一段该加延迟错位、以及在 Safari 里降级成什么才不突兀——这些没法靠一个 cubic-bezier() 函数自动解决。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











