Mastering CSS Animations with @keyframes

Abstract image used to represent Mastering CSS Animations with @keyframes
Image by Noom Peerapong.

A CSS transition handles a change between two states. @keyframes becomes useful when the animation needs intermediate stages, repetition, or more deliberate timing. The effect still has to support the interface rather than merely proving that the browser can move something.


What is @keyframes?

In CSS, the @keyframes rule enables us as developers to specify how an element's style should change at different points during an animation sequence. It provides a framework for defining key steps (or frames) in an animation timeline.

Syntax

@keyframes animation-name {
  0% { /* Initial styles */ }
  50% { /* Midpoint styles */ }
  100% { /* Final styles */ }
}

Here, we define three states for the element to animate between:

  • 0% represents the starting state of the animation.
  • 100% represents the end state.
  • We can define as many intermediate steps as our animation needs using percentages.

A Basic Example

As a very basic example, here's a simple animation which moves a box 300px across to the right over three seconds:

@keyframes moveRight {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(300px);
  }
}

.box {
  width: 100px;
  height: 100px;
  background-color: steelblue;
  animation: moveRight 3s linear;
}

In this example:

  • The animation is called moveRight.
  • The @keyframes rule defines a starting position (translateX(0) at 0%) and end position (translateX(300px) at 100%).
  • Because this is only a simple, linear animation, we only need to define the starting and end states, the browser will calculate the movement between these two.
  • This is applied to .box by specifying the animation name (moveRight), duration (3s), and timing function (linear).

Adding Intermediate Steps

Because we can define the state at any point within the animation duration (and accept that the browser will work it out for us), we can use intermediate steps to make our animations more dynamic.

Using my example from above, for example. If we add a step at 50%, we can put a step in where it moves the majority of the way rightwards (200px) in the first half of the animation duration, and then the last 100px at a slower pace.

@keyframes moveRight {
  0% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(200px);
  }
  100% {
    transform: translateX(300px);
  }
}

If we apply this with the same threesecond duration as before, then the box will move 200px in the first 1.5 seconds, and then the remaining 100px during the last 1.5 seconds half the speed.

You could also use these steps for example to produce a bouncing animation like this:

@keyframes bounce {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-50px);
  }
  100% {
    transform: translateY(0);
  }
}

.bouncing-box {
  animation: bounce 1s ease-in-out infinite;
}

Here:

  • The element moves up midway through the animation (translateY(-50px) at 50%), and returns to it's original position at the end (translateY(0) at 100%).
  • Because we're using the infinite keyword, the animation will repeat endlessly, making the .bouncing-box element bounce up and down.

Controlling Animations

Aside from defining the keyframes themselves, CSS provides several properties that allow us to control animations when using @keyframes:

  • animation-duration defines how long the animation should last (e.g., 3s or 500ms).
  • animation-timing-function controls the speed curve (e.g., ease, linear, ease-in-out, etc).
  • animation-delay delays the start of the animation.
  • animation-iteration-count specifies how many times the animation runs (e.g., 1, 2, infinite).
  • animation-direction defines whether the animation plays forwards, backwards, or alternates (e.g., normal, reverse, alternate).

These properties can also be combined together into a single shorthand animation property, using the following syntax:

animation: <animation-name> <duration> <timing-function> <delay> <iteration-count> <direction>;

For example:

animation: moveRight 3s ease-in-out 1s infinite alternate;

Browser Support

By November 2017, unprefixed @keyframes was supported by the current releases of Chrome, Firefox, Edge and Safari. Older browsers still needed separate attention:

Internet Explorer 9 and earlier do not support CSS animations; IE10 supports them without a vendor prefix. Safari 4–8 needed -webkit- prefixes, with unprefixed support arriving in Safari 9. For that older Safari support, the keyframes declaration begins like this; the corresponding animation properties also need their appropriate prefixes:

@-webkit-keyframes moveRight {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(300px);
  }
}

Wrapping Up

Key Takeaways

  • The @keyframes rule defines how an animation progresses through a timeline from 0% to 100%.
  • Use animation properties like duration, timing-function, and iteration-count to control animations.
  • Check the versions you need to support. The historical -webkit- example applies to Safari before version 9, not to IE10.
  • With its broad support in modern browsers, CSS animations are a reliable way to enhance interactivity and design.

Use keyframes when an animation needs more than a simple transition between two states. Prefer transform and opacity for smooth visual changes, keep the sequence short enough to support the interaction, and provide a reducedmotion alternative. The interface must remain understandable when the animation does not run.


Need a senior engineer involved?

I can work directly in the codebase, review the architecture, or support the team through delivery when the work needs more than extra hands.