Design & UX
Article

Understanding the CSS animation-fill-mode Property

By Louis Lazaris

I’m sure just about all of us working in front-end development have fiddled with CSS keyframe-based animations at some point. Some of us may have even created some pretty complex demos and experiments with this feature.

If you want a comprehensive introduction to the topic, my 2011 article on Smashing Magazine is still a good option. In this article, however, I wanted to focus on a single part of the CSS Animations spec: the animation-fill-mode property.

This is the one animation-based property that isn’t very self-explanatory. For example, nobody really gets confused by animation-name, animation-duration, and so forth… But what on earth does “fill mode” mean? Let’s briefly consider this, with some examples.

The Syntax for Defining a fill-mode

As you might already know, a basic keyframe animation is defined using the @keyframes at-rule. But the keyframes won’t do anything unless you associate them with an animation name. Here’s a shorthand animation property declaration, so you can see what I mean:

.example {
  animation: myAnim 2s 500ms 2 normal ease-in forwards;
}

And of course, this same shorthand line can be expanded to:

.example {
  animation-name: myAnim;
  animation-duration: 2s;
  animation-delay: 500ms;
  animation-iteration-count: 2;
  animation-direction: normal;
  animation-timing-function: ease-in;
  animation-fill-mode: forwards;
}

The animation-fill-mode property is defined last in both examples, and in both cases the value is set to “forwards”. We don’t have to define it last, but that might be a good practice to get into.

Again, even if you’ve never used CSS animations, you can probably figure out what everything in that declaration above is doing – except animation-fill-mode.

The Spec Definition of fill-mode

So what does the spec say about this property?

The animation-fill-mode property defines what values are applied by the animation outside the time it is executing.

As it goes on to explain, the time “outside” of execution, specifically, is referring to the time between when the animation is applied to the element, and the time that the element actually starts animating. Basically, with a fill-mode value, you define the appearance of your animated element outside of the time the animation is taking place, but after the animation has been applied. Might sound confusing, but you’ll see what I mean in a moment.

Let’s build on that basic definition (which might still be a bit confusing) by looking at each of the possible values.

Breaking Down the Values

The animation-fill-mode property can accept one of four values: none, forwards, backwards, or both. Here’s a breakdown of each.

Value: none

This is the initial, or default value for animation-fill-mode. The only time you would define a value of none without being superfluous would be if you are setting it via JavaScript to change it from one of the other values, or if you’re overriding something in the cascade.

To understand what a value of none does, here’s a CodePen demo showing an animation with no animation-fill-mode defined (thus, it has a value of none):

See the Pen Example with animation-fill-mode: none by SitePoint (@SitePoint) on CodePen.

You can see that in most cases, a fill-mode of “none” is not what you’ll want. Remember that fill-mode defines how the element will look, outside the time that the animation is executing.

In this example, the ball starts out red, then fades to pink while at the same time moving to the right and changing size. It would be preferable if, when the animation finished, the ball stayed small, pink, and off to the right. This will avoid the ugly jump back to the start when the animation finishes.

Value: forwards

Let’s change our ball animation to have a fill-mode value of “forwards”:

See the Pen Example with animation-fill-mode: forwards by SitePoint (@SitePoint) on CodePen.

Now you can see the benefit of using animation-fill-mode and why a value of forwards is used more than any other. When we define it with this value, we are telling the browser that we want our animated element to hold on to its final set of styles, as defined in the last keyframe. This way, we don’t get that final jump back to the initial state of the element before it started animating (the “reset” button that I’ve added to the demo does this for us).

Value: backwards

Let’s change the value to backwards — what happens now?

See the Pen Example with animation-fill-mode: backwards by SitePoint (@SitePoint) on CodePen.

Notice that the behavior in this demo is exactly the same as the first demo that has an animation-fill-mode value of “none”. Why is that?

In contrast to forwards, a value of backwards, upon finishing the animation, gives the element the styles that it had before the animation began. This makes more sense when we see what the spec says for the value backwards:

During the period defined by animation-delay, the animation will apply the property values defined in the keyframe that will start the first iteration of the animation. These are either the values of the from keyframe […] or those of the to keyframe.

To demonstrate this, I’ve made two modifications to the demo:

  • Added a “from” keyframe with a different color for the ball.
  • Added a delay using the animation-delay property.

Here it is:

See the Pen Example with animation-fill-mode: backwards (2) by SitePoint (@SitePoint) on CodePen.

Now you can see that as soon as you push the “Start The Animation” button, the ball turns blue. This is because there is a noticeable delay. Technically, every animation has a default delay, but the delay is 0s, so you don’t really see the value of backwards in such a case, and you certainly don’t see it if the styles in the initial keyframe are the same as those prior to when the animation begins. With the same styles and the same delay in place, removing the value backwards would cause the ball to stay red until the animation begins.

To be honest, I don’t really see a lot of practical use for the value backwards. It’s hard to imagine too many scenarios where the animation has different styles in the first keyframe than it does in the static pre-animation state of the element. But I’m willing to hear some use cases if you have any ideas.

Value: both

The final value we’ll look at is a value of both. This value tells the browser to apply the effects of both forwards and backwards.

Let’s keep the same styles in our demo and see what happens when we give it a value of both:

See the Pen Example with animation-fill-mode: both by SitePoint (@SitePoint) on CodePen.

Not rocket science. As you can see, during the initial delay period, the initial keyframe styles are applied, and then the animation finishes and freezes with the styles from the final keyframe (which is, as mentioned, often what you will want). And again, this value would not be very different from just using forwards if it were not for the delay and the alternate color defined in the first keyframe.

Some Notes and Tips

Based on the above, along with some details in the spec, here are some things to take note of:

  • Although I’ve somewhat minimized the importance of the values backwards and both, these could come in handy in complex animations that are controlled by scripting or user input. Use cases will abound (think: games), but only with experimenting and innovation.
  • The effect of the forwards and backwards values are reversed in cases where the animation-direction property is set to reverse. If you fiddle with the demo, you’ll see how this works.
  • Although I said that animation-fill-mode accepts only four values, remember that there are CSS-wide property values that can also be used.
  • In earlier versions of the spec, animation-fill-mode was not part of the shorthand animation property but it seems like all browsers that support keyframes are fine with it in shorthand.
  • When using animation shorthand and choosing a custom name for your animation, don’t use a name that matches valid fill-mode values (like “reverse” or “forwards”), otherwise the browser will parse the shorthand declaration assuming the name is actually a fill-mode value.

Conclusion

I hope this summary has helped you understand this property a little better. Some of this research certainly helped me understand it a little better. If you’ve done some unique things with animation-fill-mode or have any unique use cases for the different values, or corrections to this article, let us know in the discussion.

No Reader comments

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in Design, once a week, for free.