transition-timing-function 控制动画每一帧的速度分布而非时长,决定运动节奏如匀速、先快后慢等;默认 ease 实为 cubic-bezier(0.25, 0.1, 0.25, 1),非数学匀速。

transition-timing-function 改变的是什么
它不控制动画时长(那是 transition-duration 的事),而是决定“每一帧怎么动”——比如是匀速、先快后慢,还是中间突然卡一下再冲过去。浏览器默认用 ease,看着柔和,但实际是贝塞尔曲线 cubic-bezier(0.25, 0.1, 0.25, 1),不是数学意义上的匀速。
四种预设值的实际表现差异
别只记名字,要看它们在真实交互里的反馈:
-
ease:开头慢 → 中间快 → 结尾慢,适合模态框淡入,但按钮悬停会显得“犹豫” -
linear:真匀速,适合进度条或 loading 动画,但 UI 按钮用它会生硬 -
ease-in:开头慢、结尾快,像物体从静止被弹出去,慎用于关闭类操作(用户会觉得“没关稳”) -
ease-out:开头快、结尾慢,适合展开菜单,收尾有“落定感”,但开启动作容易显得突兀
cubic-bezier() 自定义曲线的坑
手调两个控制点看似自由,实际容易翻车:
- 值必须在 0–1 范围内,超出(比如
cubic-bezier(0, 0, 1.5, 1))会被整个忽略,退回到ease - 想模拟“先慢后快再慢”,不能简单拉两个点,得用工具(如 cubic-bezier.com)试,肉眼调基本靠猜
- 移动端 Safari 对复杂贝塞尔支持弱,
cubic-bezier(0.17, 0.67, 0.83, 0.67)这种三段式在 iOS 15 以下可能降级为ease
steps() 分步动画的适用场景
不是所有“变速”都要靠贝塞尔——数字计数器、打字效果、帧动画这类离散变化,steps() 更准:
立即学习“前端免费学习笔记(深入)”;
-
steps(4, start)表示分 4 步,**第一步立刻跳变**(常用于 sprite 动画) -
steps(5, end)是等分 5 次,**最后一步才完成**(适合倒计时数字切换) - 和
transition搭配时,必须确保属性本身支持离散变化(如background-position、transform: translateX()),对opacity用steps()会出视觉断层
cubic-bezier() 和 steps() 解决的是完全不同的问题,混用或硬套预设值,比写错一个 transition-property 更难排查。










