CSS Animation Steps() Basics"


This is the sprite sheet for the character were are going to animate. We’ll prepare an idle animation that might, for example, be seen in a platformer game. The final animation can be seen at the end of the article or in the accompanying pen here.

Sprite Sheet

Let’s first set up the HTML element to hold the character. All we need is a simple <div>.

<div class="character idle"></div>

Next we need some basic CSS to define the initial state of the character. This is where we will also define the sprite as a background image, positioned at 0 0 so that the first frame of the sprite appears on screen.

.character {
  background: url("character-idle.png") 0 0;
  height: 44px;
  width: 44px;
}

At this point we should see our character standing still.. frozen in time :(

First frame of character

Let’s improve his horrid existence with the magic of CSS animation! In particular we’ll take advantage of the steps() value for the animation-timing function property. This is particularly suited for sprite based animations. Here’s the code we need. I’ll explain it below.

.idle {
  animation-name: whistle;
  animation-duration: 2.1s;
  animation-iteration-count: infinite;
  animation-timing-function: steps(20);
}

@keyframes whistle {
  100% {
    background-position: -880px 0;
  }
}

animation-name: This name should match that of the keyframe definition that we want to bind to the animation. You can see this defined below the .idle class block.

animation-duration: The length of our animation. In this case 2.1 seconds feels about right to my eye, but this depends on the individual animation so wouldn’t necessarily work for a different sprite sheet.

animation-iteration-count: How often we want the animation to play. In this case we want it to repeat forever.

animation-timing-function: Here you can see the steps() function in use. We get the number 20 by dividing the width of each frame by the total width of the sprite sheet: 880 / 44 = 20, which is the number of frames in our animation.

We can shorthand this like so: animation: whistle 2.1s steps(20) infinite;

In our @keyframes definition, we’re saying that when the animation reaches 100% (ends), we want the background position of the image to be -880px along the x-axis. (0% is the initial background position we defined in the .character class). So the background position is going to move from 0 0 to -880px 0 in 2.1 seconds. At this point, if we weren’t taking advantage of the steps() functionality, our animation would look something like the following (I’ve increased the animation time to make it less jarring), moving smoothly from 0 to -880px.

Without steps()

This isn’t a very attractive animation and this is where steps() comes in. Instead of moving smoothly from one state to another, steps() allows us to define a fixed number of frames to complete the animation in. So in our code we’ve told it to transition to -880px in 20 fixed steps and since we’ve set the iteration count to infinite, the animation will continue to repeat.

Using steps() it looks a lot better! Here’s a pen with the final result.

If you’re trying this outside of my pen below, don’t forget you may need to add -webkit vendor prefixes, depending on your browser.

See the Pen

CSS Animation Steps() Basics