Animation Keyframes

Chapter 50 10 mins

Learning outcomes:

  1. What are keyframes
  2. The from and to blocks
  3. Percentage-based keyframes

What are keyframes?

At the core level, for a CSS animation to operate it needs keyframes. They denote the styles of an animation at given time frames and hence collectively form it starting from point and ending at the other.

In this chapter we will take a deeper look into how @keyframes works and in what ways to use and not use it together with a handful of examples. Let's enroll.

From and To

The most basic form of keyframes is CSS are the from{} and to{} style blocks.

from{} contains the styles to start an animation with whereas to{} contains the styles to end the animation with. In this way we form a two-state animation where the initial state is in from and the final state is in to.

Just like you would normally write CSS properties in a selector block let's say p {} for all p elements you will write style properties in these two, from and to, blocks.

@keyframes animation-name {
    from {
        /* contains the styles to
           start the animation with */
    }
    to {
        /* contains the styles to
           end the animation with */
    }
}

Here is an example of changing the opacity of the element div from 1 to 0 and letting it remain in that very position.

Can you recall anything from the word "remain" in this case? What properrty does it ask you to use in the animation? Well you need animation-fill-mode with the value forwards.
div {
    animation: opacityChanger 2s 1 forwards;
    width: 100px;
    height: 100px;
    background-color: #ffcc00;
    padding: 15px
}

@keyframes opacityChanger {
    from { opacity: 1 }
    to { opacity: 0 }
}
Change my opacity

Notice the declaration opacity: 1 in from: this means that the animation will start with setting the div to full opacity (which is by default the case for all elements in HTML). The declaration opacity: 0 in to on the other hand simply makes the animation end at this value i.e no opacity.

Let's try another example with the same div as before but this time adding opacity on it, changing the animation keyframes and oscillating between the states.

What can you remember from the word "oscillating"? Which property/paramter do you want to be using? Well you need animation-direction: alternate
div {
    animation: opacityAndWidth 2s 5 alternate;
    opacity: 0.3;
}

@keyframes opacityAndWidth {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
        width: 200px;
    }
}
Change my opacity

Did you see how the element snapped from opacity 0.3 to 1 as soon as it began animating?

And in this very way you can try out different combinations of styles in the @keyframes rule and experiment with different animation parameters, like animation-fill-mode, animation-direction and so on, to better understand all these ideas.

Now although this is the most easiest way to set up keyframes, using the blocks from{} and to{}, it doesn't give us much of a control over the mid states of the animation. We can only have two states - the initial in the from{} block and the final in the to{} block - that's it! Nothing else can go in between.

The way to get this control and be able to add multiple midway states to an animation is to use percentage keyframes.

Percentage Keyframes

In percentage keyframes, as the name suggests, we specify percentage values together with their style blocks to denote the states of an element at that particular instance of time.

The syntax is pretty simple: percentage% {}, where percentage is a value between 0 and 100 denoting a percentage value like 50% {}, 85.5555% {}, 0% {} and so on.

The percentage value accounts for a given time frame in the whole interval of an animation. For example, for an animation duration of 4 seconds, 0% {} would account for the element's state at 0s; 50% would account for the state at 2s; 75% would account for the state at 3s; 100% would account for the end of the animation at 4s and so on.

0% is the equivalent of from whereas 100% is the equivalent of to.

Simply put: the percentages are relative to the duration of the animation.

Following is a simple illustration with three states for an animation.

div {
    animation: threeStates 6s 1;
}

@keyframes threeStates {
    0% { opacity: 0 }
    50% { opacity: 1 }
    100% { opacity: 0 }
}
Change my opacity

We start with opacity: 0 at 0% i.e 0s; then upto the midway of the animation at 50% i.e 3s we animate to opacity: 1 and then finally end the animation at 100% i.e 6s with opacity: 0.

In practice, this is it for keyframes at the core of the concept. For the crust there are just a few points to remember when working with keyframes as discussed below.

Things to remember

Omitting from {} in a from-to animation or 0% in a percentage-based animation causes these states to default to the original styles of the element. Hence the animation will begin with the actual styles of the element.

div {
    background-color: #ddd;
    padding: 15px;
    width: 100px;
    height: 100px;
    animation: anim1 1s 3;
}
@keyframes anim1 {
    /* from {} has been omitted */
    /* hence it will default to the actual styles of the element */
    to { width: 250px }
}
Animate me!

Omitting to{} in a from-to animation or 100% in a percentage-based animation causes these states to default to the original styles of the element. Hence the animation will end with the actual styles of the element.

div {
    /* same styles as the one above */
}
@keyframes anim1 {
    from { width: 250px }
    /* to {} has been omitted */
    /* hence it will default to the actual styles of the element */
}
Animate me!

The !important keyword is ignored within a keyframe.

Specifying the @keyframes rule with the same name or any style block like from, to etc. within it multiple times causes the underlying styles to cascade.

div {
    /* same styles as the one above */
    animation: anim1 3s forwards
}
@keyframes anim1 {
    to { opacity: 0.5 }
    to { opacity: 0 }
    /* the second to block here cascades the first one */
    /* hence the animation will end at opacity: 0 */
}
Animate me!

Try swapping lines 6 and 7 with each other in your editot and see the result. The animation will end at opacity: 0.5 instead of opacity: 0.
Notice that we've omitted the from {} block in this example, so therefore the animation will start with the original styles of the element.