@keyframes, Beyond the Basics

Multi-step timelines, animation-fill-mode, staggering with delays, and steps() for sprite-style motion.

You know @keyframes name { from {} to {} }. The craft is in the properties that surround it.

Percentage stops build a timeline

@keyframes pop {
  0%   { transform: scale(0);   opacity: 0; }
  70%  { transform: scale(1.1); opacity: 1; }  /* overshoot */
  100% { transform: scale(1); }
}

The properties that make it usable

  • animation-fill-mode: forwards — keep the final frame's styles after it ends, instead of snapping back. This one trips up everyone.
  • animation-delay — stagger a group by giving each item a slightly larger delay for a cascading reveal.
  • animation-iteration-count — a number, or infinite.
  • animation-direction: alternate — play forward then backward, so a loop breathes instead of resetting.
  • animation-timing-function: steps(n) — jump in discrete steps for sprite sheets and typewriter effects.

Set them all at once with the animation shorthand once you're comfortable with the order.

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A developer uses animation-fill-mode: forwards to keep a fade-in element at full opacity after the animation completes.
  • A developer staggers list item animations with animation-delay: calc(var(--i) * 0.1s) so items animate in one after another.
  • A designer uses steps(8) for a sprite-based walking animation so the sprite advances one frame at a time instead of interpolating.

More examples

fill-mode and delay staggering

Stagger each list item using a CSS custom property as a delay multiplier and forwards fill-mode to keep the end state.

Example Β· css
@keyframes fade-up {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}

.list-item {
  animation: fade-up 0.4s ease forwards;
  animation-delay: calc(var(--i, 0) * 80ms);
  opacity: 0; /* starting state before animation */
}

Multi-step @keyframes timeline

Uses three percentage stops to change both width and color, simulating a progress bar moving through status phases.

Example Β· css
@keyframes progress {
  0%   { width: 0;    background-color: #2965f1; }
  60%  { width: 60%; background-color: #2965f1; }
  80%  { width: 80%; background-color: #f39c12; }
  100% { width: 90%; background-color: #c0392b; }
}

.progress-bar {
  height: 8px;
  animation: progress 4s ease-in-out forwards;
}

steps() for sprite animation

Uses steps(8) to jump through eight sprite frames discretely, creating frame-by-frame sprite animation without interpolation.

Example Β· css
@keyframes run {
  to { background-position: -512px 0; }
}

.sprite {
  width: 64px;
  height: 64px;
  background-image: url('runner-sprite.png');
  animation: run 0.8s steps(8) infinite;
}

Discussion

  • Be the first to comment on this lesson.
@keyframes, Beyond the Basics β€” CSS | SoundsCode