CSS动画生硬主因是缓动函数选择不当;应善用cubic-bezier()自定义曲线,如轻微弹跳入场cubic-bezier(0.25,0.46,0.45,0.94),并按属性分设transition-timing-function以提升自然感。

CSS动画生硬,通常不是因为动画本身有问题,而是timing-function(缓动函数)没选对。默认的 ease 虽然比 linear 好一点,但依然偏“机械”,缺乏真实物理感。关键在于用对缓动曲线,让运动有加速、减速、回弹或弹性,才显得自然。
用好 cubic-bezier() 自定义曲线
浏览器内置的 ease、ease-in、ease-out、ease-in-out 都是预设的贝塞尔曲线,但它们太通用,不够贴合具体动效需求。真正灵活的方式是手写 cubic-bezier(x1, y1, x2, y2):
- x1, y1:起点控制点(影响起始加速度)
- x2, y2:终点控制点(影响结束减速/回弹)
- x 值必须在 0–1 之间;y 值可超出范围(比如 y = -0.2 或 1.8),实现“overshoot”(过冲)或“bounce-like”效果
推荐从 cubic-bezier.com 可视化调试——拖动控制点实时预览,再复制代码到 CSS 中。
常用自然感缓动组合(直接可用)
这些值经过大量 UI 实践验证,比默认更柔和、有呼吸感:
立即学习“前端免费学习笔记(深入)”;
-
轻微弹跳入场:
cubic-bezier(0.25, 0.46, 0.45, 0.94)—— 适合按钮悬停、卡片展开 -
平滑收尾(防突停):
cubic-bezier(0.34, 1.56, 0.64, 1)—— y1 > 1 制造减速后微回弹,告别“戛然而止” -
模拟重力下落:
cubic-bezier(0.22, 0.61, 0.36, 1)—— 先快后慢,带点惯性 -
轻量弹性收起:
cubic-bezier(0.68, -0.55, 0.27, 1.55)—— y 值正负越界,产生小幅反弹
搭配 transition-timing-function 和 animation-timing-function 的细节
别只盯着 animation,交互反馈类动画(如 hover、focus)更依赖 transition 的缓动设置:
- 给
transition单独指定 timing-function,比写在animation里更易维护 - 避免全写成
all 0.3s ease—— 不同属性(transform vs opacity)适合不同缓动,建议按属性拆分:transform 0.3s cubic-bezier(...), opacity 0.2s ease-out - 动画循环时(
animation-iteration-count: infinite),结尾和开头的缓动要衔接自然,优先选对称或首尾导数接近的曲线(如ease-in-out或自定义对称贝塞尔)
进阶:用 @keyframes 分段控制节奏
单一缓动函数无法覆盖复杂运动。例如一个图标“放大 → 微抖 → 停稳”,可以在 @keyframes 中分阶段设置不同缓动:
- 0% → 70%:用
ease-out快速放大 - 70% → 90%:用
ease-in短暂反向收缩(制造抖感) - 90% → 100%:用
cubic-bezier(0.25, 0.95, 0.45, 1)缓慢收至最终态
每一段都能配独立 animation-timing-function(通过 animation-timing-function 属性不支持分段,但可通过多个 animation 叠加或 JS 控制节奏实现)。
缓动不是炫技,而是让界面“有重量、有惯性、有回应”。调对一条曲线,比加三个动画效果更有效。










