说实话,做前端动效这几年,我见过很多开发同学把按钮的 transition 加上 0.3s 就觉得大功告成,结果交上去后被设计师一句“动画很生硬”打回。问题往往不在时长,而在一个最容易被忽略的细节——缓动函数。很多 CSS 动画之所以看起来像“尸体在平移”,就是因为从头到尾都是线性运动,而现实世界几乎没有东西会匀速运动。这篇文章就专门把缓动函数这件事讲透:它到底是什么、为什么能让动画有真实感、内置的几种曲线该怎么选、自定义 cubic-bezier() 怎么调出弹簧质感,以及我在项目里踩过的各种坑。无论是刚入门的前端,还是被动效折磨过的 UI 开发,甚至是想理解动画原理的交互设计师,都能在这篇里找到可以直接抄的答案。
1. 缓动函数到底在解决什么问题
1.1 “匀速”其实是假象
我们先想一个生活场景:你推一个放满书的行李箱,从静止到动起来,是不是要花很大力气,一开始速度特别慢,然后才越推越快?反过来,你让行李箱滑行到墙边停下,它也不会突然“啪”一下定住,而是会先快速滑动、再慢慢减速、最后才停稳。这种“启动慢、中途快、结束慢”的节奏,才是真实世界里物体运动的常态。
而 CSS 默认的 linear(线性)缓动,等于把一个物体的速度全程锁死,从头到尾都没变化。你想想,现实生活中哪有物体能瞬间从 0 加速到匀速,再瞬间从匀速降回 0?没有。所以使用 linear 做 UI 动效时,人的眼睛会下意识地觉得“不对劲”,但又说不上哪里不对。这种直觉差异,就来自物理世界和数字世界的节奏冲突。
缓动函数解决的就是这个冲突。它的本质是“给时间加滤镜”:动画从 0% 跑到 100% 的过程中,每到一个时间点究竟该完成多少进度,由缓动函数说了算。线性缓动就像把 1 秒平均切分成 100 份,每秒完成的比例完全一样;而缓动曲线则可以把前 200ms 的完成度压低、把中间 200ms 的完成度拉高,让动画看起来像是有惯性和阻力。
1.2 用“变速箱”理解缓动函数
你可以把 CSS 动画的播放想象成开车:时间轴是一条路,元素是车,而缓动函数就是变速箱和油门踏板的配合逻辑。linear 相当于定速巡航,全程一个速度;ease-out 则是起步时给了一脚大油门、之后慢慢松开;ease-in 相反,前段一直在轻点油门,后段才猛踩下去。
这里有一个关键认知:缓动函数改变的并不是“动画要不要播”,而是“每一帧里元素的属性值到底走到哪”。transition 的 1s 不会因为曲线而变长或变短,变的只是第 300ms 时,元素是已经走了 70% 还是只走了 30%。理解这一点很重要,因为你做动效节奏控制时,头脑里要有“完成度”这个概念,而不是简单觉得“动画就是属性从 A 变成 B”。
1.3 三种常见的写法位置
CSS 里使用缓动函数有三个层面:
- 写在 transition 简写属性里,例如
transition: transform 0.3s ease-out; - 写在 animation 简写属性里,例如
animation: fadeIn 0.6s cubic-bezier(.16,1,.3,1); - 写在 @keyframes 内部的具体关键帧上,例如在 40% 处设置
animation-timing-function: ease-in,这会让关键帧到下一个关键帧之间的片段使用该曲线。
前两种大家应该很熟,第三种容易被忽略。它的用途很有意思:如果你一段动画里有多个阶段,比如一个小球先减速上升、再加速下落,你不可能用一个全局缓动函数同时满足这两个阶段,就得在关键帧中间切换曲线。后面我会专门写一个例子说明怎么写。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 四种内置缓动曲线,到底该怎么选
2.1 先给四个“默认选手”做个性格测试
CSS 里最常用的四个内置值,每个都有鲜明的“性格”,我把它们对照记忆成不同的人走路方式,你一下就能分清:
ease:默认值,相当于一个“谨慎的普通人”。起步稍慢,中段加速,后段再慢下来。整体比较平均,适合大多数通用过渡,但动效偏柔。ease-in:相当于“拖着沉重货物的人”,一开始很费劲,速度起不来,越到后面越快,冲劲很足。适合做出场、下落、被移出视野的效果。ease-out:相当于“正常起步然后准备靠站停车的人”,起步很干脆,后段有优雅的刹车感。适合入场、展开、出现类动效。ease-in-out:相当于“地铁列车进站出站”,两头都慢,中间快。适合做来回循环的动画,比如 loading 旋转、脉动呼吸灯、模态框在屏幕中央放大缩小。
很多人以为 ease 和 ease-in-out 差不多,但实际用起来差异很大。ease 的前半段速度偏快,适合短平快的 hover 反馈;ease-in-out 的两头减速会拉长开始和结束时的“存在感”,更适合展示型动效,不适合那种需要立刻响应的微交互。
2.2 用一张表快速选型
我在实际项目里通常会按动效的用途做快速匹配,整理成下面这张选型表,基本 90% 的 UI 场景都能覆盖:
| 动效类型 | 推荐缓动 | 原因 |
|---|---|---|
| 按钮 hover、按下 | ease-out 或自定义短贝塞尔 | 需要立刻响应,尾部有点缓冲才柔和 |
| 弹窗/面板入场 | ease-out | 入场时要果断出现,尾部慢慢停机 |
| 弹窗/面板离场 | ease-in | 离场时要有被“吸走”的感觉,收尾更干脆 |
| 元素从视野外飞入 | cubic-bezier(.22,.61,.36,1) | 比 ease-out 更利落,不太拖沓 |
| 元素落下、掉出容器 |
