CSS动画时间函数timing-function_理解ease与steps步进效果

6次阅读

ease 是有惯性启停的缓动,非匀速或静止启停;steps() 是离散时间切片,步数和 jump 关键字决定状态切换时机,混用 ease 与 steps 无效。

CSS动画时间函数timing-function_理解ease与steps步进效果

ease 是缓动,不是匀速,更不是“慢慢开始再慢慢结束”的模糊描述

很多人看到 ease 就默认它是“先慢后快再慢”,其实这是对 cubic-bezier(0.25, 0.1, 0.25, 1) 的过度简化。它的真实曲线在开头和结尾斜率不为零,意味着起始和结束都有加速度——不是停顿,而是“有惯性地启停”。

实操建议:

  • devtools 的动画面板拖拽贝塞尔曲线手柄,观察时间轴上 progress 的实际分布,比背口诀管用
  • 如果想真正“从静止启动+静止停止”,ease-in-out 更接近(cubic-bezier(0.42, 0, 0.58, 1)),但依然不是完全归零斜率
  • ease 在长周期动画(>1s)中容易显得“拖沓”,因为中间段速度偏高,人眼会忽略加速/减速段

steps() 不是“帧动画”,是离散时间切片,步数和 jump 关键字决定落点

steps(4, end) 不等于“播放4帧 GIF”,它把整个动画时长等分为4段,在每段**结束时**瞬间跳到下一个状态;而 steps(4, start) 是在每段**开始时**就跳。这个“jump”位置直接影响视觉节奏感。

常见错误现象:

立即学习前端免费学习笔记(深入)”;

  • steps(5) 却没意识到默认是 end,导致第一帧空白(第0%状态不显示),动画像“少播一帧”
  • steps(1) 想实现“开关式切换”,结果发现还是有过渡——因为 steps(1, end) 表示:0–100% 全程保持初始值,100% 时刻才跳终值;想立刻跳,得用 steps(1, start)
  • 配合 @keyframes 使用时,若关键帧只有 0%100%steps(n) 实际只产生 n+1 个离散状态(含起始),不是 n 次变化

ease 和 steps 混用会失效,transition-timing-function 只认一个值

写成 transition-timing-function: ease, steps(3); 是无效的——css 不支持多 timing-function 同时作用于同一属性。浏览器会直接丢弃整条声明或只取第一个(取决于解析策略),结果往往是回退到 ease

使用场景与替代方案:

  • 想让位移用 ease、透明度用 steps(2)?必须拆成独立 transitiontransition: transform 0.3s ease, opacity 0.3s steps(2);
  • 想在一个动画里先缓动再步进?不能靠单个 transition,得用 @keyframes + animation-timing-function: steps(2) 配合关键帧位置控制
  • 注意 transition 的 timing-function 对所有过渡属性生效,除非显式按属性拆分

steps 的兼容性没问题,但 safari 对 start/end 的处理曾有偏差

ios 13.3 之前,Safari 把 steps(2, start) 解析成类似 steps(2, end),导致第一帧意外显示终值。现在已修复,但如果你还要支持老版本 iOS,得加降级:

animation-timing-function: steps(2, start); animation-timing-function: -webkit-steps(2, start); /* 旧 Safari */

性能影响很小——steps() 是纯时间切片,不触发重排,但若配合频繁变化的 transformopacity,仍需确保元素开启硬件加速(will-change: transformtransform: translateZ(0))。

最容易被忽略的是:steps 的“步数”必须是整数,传 steps(2.5) 会被忽略,回退到 ease,且不会报错,很难排查。

text=ZqhQzanResources