背景:CSS 动画的关键帧与时间函数
关键帧在动画中的角色
在前端开发中,CSS 动画的核心在于通过 @keyframes 定义的关键帧来描述从初始状态到结束状态的过渡过程。只有明确了每一个关键点的样式,浏览器才能在时间轴上生成连贯的过渡效果。关键帧的存在决定了动画的形态与走向。
如果在样式中没有定义任何 @keyframes,则对应的 animation 无法产生可观测的变化,动画会被浏览器视为无效状态。这一点是理解“省略关键帧的 CSS 动画”现象的基础。
step-start 的工作原理及应用场景
把控动画节拍的时间函数
在 CSS 动画中,step-start属于时间函数的一种,表示以“步进”的方式推进动画的时间进度。它会让动画在每一个时间段的起点完成一个跳跃式的状态更新,适合需要离散帧的场景。通过将 animation-timing-function设置为 step-start,可以改变帧之间的过渡密度与触发时点。
需要注意的是,step-start对具体帧的定义并没有改变“必须存在关键帧”的基本要求,它只是决定了在有限的关键帧集合中,何时从一个帧跳跃到下一个帧。换言之,没有关键帧,step-start 也无法发挥作用。
animation-fill-mode: both 的含义与应用
前后状态保留与可预期的最终呈现
animation-fill-mode: both意味着:在动画执行前的起始阶段和执行结束后的阶段,元素都按照动画的起始值和结束值进行呈现,确保视觉状态在前后两端都保持一致。这个属性对于需要在动画之外仍展示最终效果的场景非常有用。

结合 step-start等时间函数,fill-mode可以让离散帧的起点和终点在视图上保持可见,从而实现更稳定的设计语言。不过,前提仍然是必须有一个有效的 @keyframes 序列来定义这些状态的具体样式。
省略关键帧的 CSS 动画是否可行?原理分析
没有关键帧会怎样?
按照 CSS 标准,animation-name 所引用的必须是一个已定义的 @keyframes 规则;若没有对应的关键帧,浏览器通常会把该动画视为无效,不会产生任何中间过渡。换句话说,所谓“省略关键帧的 CSS 动画”在现实浏览器实现中并不会真的工作,关键帧定义缺失等同于动画不可用。
即使设置了 animation-fill-mode: both,也无法在没有关键帧的情况下产生起始或结束状态的过渡效果,因为没有可插值的状态集合来支撑该填充行为。下面的示例直观地说明了这一点:如果只写了 animation-name、时长和计时函数,却没有定义任何 @keyframes,浏览器会直接忽略这段动画。
/* 错误示例:没有定义 @keyframes,动画将无效 */
.box {width: 100px; height: 100px; background: #4a90e2;animation-name: slide; /* 未定义 @keyframes slide { ... } */animation-duration: 2s;animation-timing-function: step-start;animation-fill-mode: both;
}
实战示例:正确组合 step-start 与 both 的 CSS 动画
一个可复现的最小示例
真正要实现稳定的动画效果,必须提供明确的 @keyframes,并在需要的阶段应用 step-start 以及 animation-fill-mode: both。下面给出一个可直接运行的最小示例,用来演示正确的组合用法。
示例一:简单位移动画 通过 step-start 将位移动作分成若干步进行,且动画结束后保留最终状态。
<div class="box" aria-label="animated box"></div>
/* CSS */
@keyframes slide {0% { transform: translateX(0); opacity: 0; }100% { transform: translateX(120px); opacity: 1; }
}
.box {width: 60px; height: 60px; background: #3cb371;animation-name: slide;animation-duration: 1.2s;animation-timing-function: step-start;animation-fill-mode: both;
}
示例要点:明确的 @keyframes 定义、step-start 调整帧进度,以及 both 保留起始与结束状态,确保动画在结束后仍然可见。
若需要多步分段,可以将 steps(n, start) 替代 step-start,以实现更细的离散控制,并同样配合 animation-fill-mode: both 使用。
/* 另一种实现:多步离散帧 */
@keyframes stepPulse {0% { transform: scale(1); background: #3f51b5; }33% { transform: scale(1.05); background: #5c6bc0; }66% { transform: scale(0.98); background: #3f51b5; }100% { transform: scale(1); background: #3f51b5; }
}
.box {width: 80px; height: 80px;animation-name: stepPulse;animation-duration: 1.8s;animation-timing-function: steps(3, start);animation-fill-mode: both;
}
常见错误与排查要点
排错清单与调试方法
在调试过程中,最常见的问题是 @keyframes 不存在、名称不匹配、或浏览器厂商前缀导致的兼容性问题。确保 animation-name 指向一个实际存在的 @keyframes,并且名称严格一致。
此外,动画仅在可 animatable 的属性上生效,如 transform、opacity、top/left 等。若试图对非动画属性设置动画,浏览器会忽略该声明。


