看懂 CSS 贝塞尔曲线:四个控制点如何决定缓动函数的手感
讲清 CSS cubic-bezier 缓动函数的四个控制点怎么工作,ease 和 ease-in-out 对应什么数值,以及怎么调出自己想要的动画手感,配可实时预览的编辑器。
看懂 CSS 贝塞尔曲线:四个控制点如何决定缓动函数的手感
写 CSS 动画时,transition-timing-function 那一栏大部分人填的是 ease 或 ease-in-out,填完很少再回头看。可一旦动画"感觉不对",问题往往就出在这里。三次贝塞尔曲线(cubic-bezier)是 CSS 缓动函数的底层模型,搞懂它的四个控制点,你就能从"差不多就这样"升级到"我知道为什么要这样调"。
cubic-bezier 的四个数字到底是什么
CSS 里写 cubic-bezier(x1, y1, x2, y2),四个数字是两个控制点的坐标:P1 是 (x1, y1),P2 是 (x2, y2)。曲线的起点固定在 (0, 0),终点固定在 (1, 1),你能动的只有中间这两个手柄。
横轴 X 是时间轴,从动画开始到结束;纵轴 Y 是取值轴,0 代表起始态,1 代表结束态。这就解释了一个常被问的限制:X 必须落在 [0, 1] 区间,因为时间不能倒流;但 Y 可以超出这个范围,Y 大于 1 表示元素冲过终点再回来(overshoot,过冲),Y 小于 0 表示先反向蓄力再前进(anticipate)。bounce 和 elastic 这类弹性曲线就是靠把 Y 拉出 [0, 1] 做出来的。
ease、ease-in-out 这些关键字对应什么数值
CSS 的五个标准关键字,本质上都是 cubic-bezier 的别名:
linear=cubic-bezier(0, 0, 1, 1),匀速,看起来很机械ease=cubic-bezier(0.25, 0.1, 0.25, 1),浏览器默认,起步稍快、收尾平缓ease-in=cubic-bezier(0.42, 0, 1, 1),慢起步ease-out=cubic-bezier(0, 0, 0.58, 1),快起步、缓收尾,入场动画的好默认ease-in-out=cubic-bezier(0.42, 0, 0.58, 1),两头慢、中间快
记住 ease = 0.25, 0.1, 0.25, 1 这一组数字很有用:很多人以为浏览器默认是"匀速"或"线性",其实它的 Y1 是 0.1,起步那一下并不慢。如果你想要一个比默认更克制的缓动,把 P1 往右下挪一点就行。
一个真实的例子:从 ease 调到自己想要的手感
我自己做一个抽屉(drawer)滑入的时候,先用了 ease,总觉得收尾那一下"飘",停得不干脆。把它丢进 三次贝塞尔曲线编辑器,拖动 P2 把 x2 从 0.25 拉到 0.18,数值变成 cubic-bezier(0.25, 0.1, 0.18, 1),收尾立刻变利落,小球预览里能明显看到末段速度衰减得更陡。前后就改了一个数字,但抽屉"停住"的那一帧从拖泥带水变成了干脆落位。
这就是控制点的价值:你不是在四个数字里盲猜,而是看着曲线和动画一起改。
不只是 transition,值在哪里都通用
cubic-bezier 字符串是自包含的,同一条曲线可以填进 transition-timing-function、animation-timing-function,也能搬到 Framer Motion 的 ease 数组或 GSAP 的 CustomEase 里。这意味着你在编辑器里调好一条"主缓动",整个设计系统都能引用它。
需要注意跨库的参数顺序:CSS 和 Framer 都是 (x1, y1, x2, y2),而 GSAP 的 CustomEase 接收的是 SVG 路径。顺序搞混,曲线就会"看着差不多但又不对"。
几个容易踩的坑
第一,别给透明度用 overshoot 曲线。opacity 封顶在 1,Y 大于 1 的那段会被截成"停在不透明"的卡顿,视觉上就是闪一下。这类曲线只适合用在 transform 上。
第二,调曲线要在生产时长下调。同一条曲线 1.2s 顺滑,250ms 可能就拖沓,因为眼睛在 250ms 内根本看不到曲线中段。先定时长,再调形状。
第三,别一律用 linear。现实里几乎没有匀速运动,入场默认 ease-out、状态切换默认 ease-in-out 都比它自然。
调好缓动之后,如果你的动画还涉及位移、缩放或旋转,可以顺手用 CSS Transform 生成器 把变换部分也一起生成,缓动和变换两块拼起来,一段完整的 CSS 动画就成型了。
把四个控制点当成你能直接操纵的旋钮,而不是从别处抄来的魔法数字,CSS 动画的手感就从此可控了。
Made by Toolora · Updated 2026-06-13