Static animations with CSS Animation

This article is a part of my Web Animations article series.

Beside CSS Transition you can use CSS Animation to create static animations. But what is the difference?

  • CSS Transition: interpolates the visual representation between two states of an element. The target state is set using JavaScript by adding / remove a CSS class or setting the styleof an element directly.
  • CSS Animation: interpolates the visual representation between multiple states of an element. In comparison to CSS Transition there is no need to trigger the animation with JavaScript.

Another downside of CSS Animation: you can’t control or influence the CSS Animation despite stopping or starting it.

Keyframes

The people who specified CSS Animation used a terminology analogue to filmmaking. We create “keyframes” to define our animation:

@keyframes NAME-OF-WHAT-IT-DOES {
/* write each keyframe here */
}

Nice to know: “A keyframe in animation and filmmaking is a drawing that defines the starting and ending points of any smooth transition.” (Wikipedia)

For us these keyframes are equal to different states to interpolate between.

A single keyframe consists of two things:

  • a value for the progress of the current animation iteration (just remember “progress”)
  • corresponding CSS properties for that state

The progress is a value between 0.0 and 1.0 specified in percent notation where 0.0 (0%) indicates the start of the animation iteration and 1.0 (100%) indicates the end of the animation iteration.

Image: Eadweard Muybridge

I am talking about animation iteration because an animation can be played multiple times (repeating) or even be infinite. If we play the animation over multiple iterations the browser will jump from keyframe 100%back to keyframe 0%. When we target a smooth animation we need to make sure the properties of keyframe 0% and keyframe 100% are the same.

Let us define the keyframes for a simple animation:

@keyframes move-to-the-side {
0% {
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
100% {
transform: translateX(0);
}
}

It means: we define a set of keyframes move-to-the-side. At the start of the animation (0%) the element shouldn’t be moved. In the middle of the animation (50%) we want to have the element moved 100px to the right. After that we want our element at the end of the animation (100%) not to be moved again.

Next we need to tell the browser that he should use these keyframes for an animation of an element. Let’s apply it to our box:

.box {
width: 100px;
height: 100px;
background-color: tomato;
animation: move-to-the-side 2000ms infinite;
}

It means: we want to animate an element selected by .box to have an animation based on the keyframes move-to-the-side for a duration of 2000ms to repeatinfinite times.

Take a look at the result:

A circling box

In our keyframes we can define an arbitrary amount of states. Here is a more complex example:

@keyframes clockwise-movement {
0% {
transform: translate(0px, 0px);
}
25% {
transform: translate(100px, 0px);
}
50% {
transform: translate(100px, 100px);
}
75% {
transform: translate(0px, 100px);
}
100% {
transform: translate(0px, 0px);
}
}

These keyframes let our box move clockwise in a circle. Actually it’s not a very precise circle. But feel free to add more states to get a smooth circle.

Here is what it looks like:

Notice that I added a click function that starts and stop the animation. I just extracted the animation property to an extra class that I can toggle. When you stop the animation you will apparently notice that the box will immediately teleport to it’s origin position.

In reality the transform property of our element never gets touched. The browser just interpolates the “visual illusion” of a transform change.

Fixing “the teleport” when stopping

Finally let us discuss how to fix that sudden teleport behavior when we stop our CSS Animation.

There is a CSS property animation-play-state that can be running or paused . When you pause the animation the progress will freeze and the animation will stop in place:

You can register for the animationiteration event and use it as the perfect moment to remove the animation property from your element. Until we reach the end of an iteration we need to remember that we want to stop. Not very elegant but it works:

Implications of static animations

You saw that both CSS Transition and CSS Animation are fully managed by the browser. That is good because it’s really easy to create an animation.

On the other side we have no influence on what is happening during each animation iteration. This is where dynamic animation come into play!

Also CSS Animation aren’t very flexible or parameterizable. We can’t just decide that the box should move 200px instead of 100px at runtime. We need to write a second set of keyframes where the box moves 200px. And in the moment we exchange the 100px animation with the 200px animation, the 200px animation just start from the beginning. There will be no smooth transition.

Software Developer, http://felix-blaschke.de