loading...
Cover image for Tricking the human eye with CSS animation steps

Tricking the human eye with CSS animation steps

bornasepic profile image Borna Šepić ・3 min read

This article was inspired by the amazing Drew Conley the author behind the Danger Crew, a video game made with the technologies we all love (HTML, JS, CSS).

I listened to a podcast episode he appeared in on Syntax where he talked about the game and the processes behind it. One of the things that intrigued me the most was the way they created the animations for the characters, basically, it's just an image and some CSS animation magic... Could it really be that "simple"?

Well... Yes it is

In case you have no idea what I'm talking about, here's a quick rundown!

The image

Alt Text

Wait what?

So let's break down what we have here (please note I'm far from a graphics designer, and I really wanted to make this look better but... there really is a maximum number of hours you can spend adding shapes in Figma to an image before you lose your sh**).

Basically what we have here are are the four frames we'll be showing in quick succession to trick the human eye into seeing an actual animation.

Don't believe me? Let's write some HTML & CSS and see 😏

HTML

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="styles.css"/>
    <title>CSS Step Animation</title>
</head>
<body>
    <div class="car-container"></div>
</body>
</html>

All we will do here is include our stylesheet and add a container div which will contain our animation.

CSS

This is where the magic happens 🎉

.car-container {
    height: 87px;
    width: 210px;
    background-image: url("./car.png");
    animation: play 0.8s steps(4) infinite;
}

@keyframes play {
    from {
        background-position: 0px 0px;
    }
    to {
        background-position: -840px 0px;
    }
}

Let's first break down the properties we've assigned to the .car-container class.

We've set the height property to match the actual height of the image.
We've also set the background-image to the before provided image, feel free to download it or include it via a link.

So why is the width not set to the 840px (the width of the image)?
Because we want to only show one "frame" at a time, this is why we have set the .car-container width to 210px (1/4 of the total width).

Before taking a look at the animation property, let's first see what we are doing in the definition of the play animation.

If you're not familiar with keyframes, essentially what's going on, we are defining an initial state for a CSS property (from). And giving it an end state (to). This allows us to control the intermediate steps in a CSS animation sequence. If you'd like to dive into it more here's an excellent article at css-tricks.

All we are changing here is the background-position property, basically, we are moving the image to the left.

So how does any of this actually work?
The reason this all actually works is the steps argument in our animation property.
If you've been following along through your IDE (or in Notepad 😱), I'd recommend stopping here and removing the steps(4) from the animation property to see what happens.

Steps allows us to specify how many keyframes an animation uses to get from point a (from) to point b (to).
Since we only have four frames in our image, we will only go through four steps before repeating the circle.

End result:

So it turns out... It really is that simple

Huge shoutout to Drew Conley and the Syntax podcast for creating awesome content!

Discussion

markdown guide