steps()函数本质是离散跳变而非平滑缓动,将动画等分为指定帧数并瞬间切换,适用于复古位图帧动画;关键参数为帧数和跳变时机(end更常用),配合background-position或transform实现精灵图逐帧播放,需注意像素对齐、overflow隐藏及safari兼容性问题。

steps() 函数的本质是“跳变”,不是缓动
steps() 不是让动画平滑过渡,而是把整个动画过程切成等份,每份之间瞬间切换。做复古位图帧动画(比如 8-bit 游戏角色行走)时,你依赖的不是渐变,而是「一帧停住、下一帧突变」的机械感。它和 ease 或 cubic-bezier() 完全不同类——后者插值,前者离散。
关键参数只有两个:steps(4, end) 中的 4 表示切 4 帧,end 表示在每段**结束时**跳到下一帧(更常用);start 则是在每段**开始时**就跳,容易导致首帧闪一下,多数情况避开。
常见错误现象:steps(4) 写成 steps(4, start) 后第一帧一闪即逝;或把帧图背景设为透明却忘了父容器也透明,导致切换时透出底层内容,误以为动画“错位”。
用 background-position 实现精灵图逐帧播放
这是最轻量、兼容性最好的做法。把所有帧横向/纵向拼成一张大图(sprite),用 background-position 沿单轴移动,配合 steps() 控制停顿点。
假设你有一张横向排列的 6 帧精灵图,每帧宽 32px,总宽 192px:
div.sprite {
width: 32px;
height: 32px;
background-image: url('walk.png');
background-size: 192px 32px;
animation: walk 0.6s steps(6, end) infinite;
}
@keyframes walk {
0% { background-position-x: 0; }
100% { background-position-x: -192px; }
}
注意点:
-
background-position-x: -192px是终点,但因steps(6, end),实际只停在 -0px、-32px、-64px…-160px 这 6 个位置,不会真跑到 -192px(那会空白一帧) - 务必设
background-size,否则高缩放下帧会模糊或错位 - 如果帧数多、图大,用
will-change: background-position可提升部分浏览器渲染帧率
transform + steps() 也能做,但要注意 transform-origin 和像素对齐
用 transform: translateX() 移动一个包含多帧的内层容器,比 background-position 更灵活(比如想加旋转),但也更容易出问题。
典型结构:
<div class="anim-container"> <div class="frame-strip"></div> </div>
对应 CSS:
.anim-container {
width: 32px; height: 32px;
overflow: hidden;
}
.frame-strip {
width: 192px; height: 32px;
animation: slide 0.6s steps(6, end) infinite;
}
@keyframes slide {
0% { transform: translateX(0); }
100% { transform: translateX(-192px); }
}
容易踩的坑:
- 没设
overflow: hidden→ 多帧全部可见,变成“拉幕”效果而非逐帧 - 没设
transform-origin: 0 0→ 某些浏览器下 translate 计算偏移有亚像素误差,帧边缘发虚 - 用 rem/em 单位定义尺寸 → 缩放后帧宽不是整数像素,导致位图出现抗锯齿,失去复古感;坚持用
px
IE 和 Safari 对 steps() 的兼容细节不能忽略
IE10+、Edge 12+、Chrome 24+、Firefox 16+ 都支持 steps(),但 Safari(尤其 iOS 9–13)有个经典 bug:当 animation-duration 小于 0.1s 时,steps() 可能退化为线性行为,帧直接糊成一片。
解决方案很实在:
- 最低动画时长设为
0.1s起步,比如 6 帧就用0.6s,别为了“快”写成0.06s - 避免在
@keyframes里写百分比中间帧(如16.6%),Safari 旧版解析不稳;只写0%和100% - 需要适配 IE9?它完全不支持
steps(),只能降级为 JS 定时器 + class 切换,不推荐——真要兼容就放弃纯 CSS 方案
复古动画的魅力恰恰藏在这些硬边界里:帧数固定、时长固定、像素对齐固定。一旦松动其中一项,8-bit 就变成了低保真。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











