W3docs

CSS animations

Learn CSS animations and how to control them from JavaScript: toggle classes to start and stop them, and react to animation events.

CSS animations provide a sophisticated way to enhance user experience with smooth, visually appealing transitions and effects. In this comprehensive guide, we delve into the nuances of CSS animations, providing detailed explanations, examples, and best practices to create dynamic and responsive designs.

Introduction to CSS Animations

CSS animations enable web developers to animate HTML elements without relying on JavaScript. They are defined using keyframes, which specify the styles at various points in the animation sequence.

Basic CSS Animation Example

<div class="animated-box"></div>

<style>
  .animated-box {
    width: 100px;
    height: 100px;
    background-color: red;
    animation: move 4s infinite;
  }

  @keyframes move {
    0% { transform: translateX(0); }
    50% { transform: translateX(200px); }
    100% { transform: translateX(0); }
  }
</style>
Warning

Always test animations across different devices and browsers to ensure smooth performance.

Key Properties of CSS Animations

  • animation-name: Specifies the name of the keyframes.
  • animation-duration: Defines the duration of the animation.
  • animation-timing-function: Sets the speed curve of the animation.
  • animation-delay: Delays the start of the animation.
  • animation-iteration-count: Defines the number of times the animation should be played.
  • animation-direction: Specifies whether the animation should play in reverse on alternate cycles.

Applying Multiple Animations

You can apply multiple animations to a single element by separating them with commas.

<div class="multi-animated-box"></div>

<style>
  .multi-animated-box {
    width: 100px;
    height: 100px;
    background-color: blue;
    animation: move 4s infinite, rotate 2s infinite;
  }

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

  @keyframes rotate {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
</style>

Advanced Techniques

Responsive Animations

Ensure animations are responsive and adapt to different screen sizes.

<div class="responsive-box"></div>

<style>
  .responsive-box {
    width: 50vw;
    height: 50vw;
    background-color: green;
    animation: resize 4s infinite;
  }

  @keyframes resize {
    0% { width: 50vw; height: 50vw; }
    50% { width: 70vw; height: 70vw; }
    100% { width: 50vw; height: 50vw; }
  }
</style>

Combining Transformations

Combine multiple transformation properties to create complex animations.

<div class="complex-transform-box"></div>

<style>
  .complex-transform-box {
    width: 100px;
    height: 100px;
    background-color: yellow;
    animation: complexTransform 5s infinite;
  }

  @keyframes complexTransform {
    0% {
      transform: translateX(0) rotate(0deg) scale(1);
    }
    50% {
      transform: translateX(200px) rotate(180deg) scale(1.5);
    }
    100% {
      transform: translateX(0) rotate(360deg) scale(1);
    }
  }
</style>

Animation Fill Modes

The animation-fill-mode property defines how a CSS animation applies styles to its target before and after its execution.

<div class="fill-mode-box"></div>

<style>
  .fill-mode-box {
    width: 100px;
    height: 100px;
    background-color: purple;
    animation: fillMode 3s forwards;
  }

  @keyframes fillMode {
    0% { background-color: purple; }
    100% { background-color: orange; }
  }
</style>

Animation Delays and Timing Functions

Use animation delays and timing functions to control the pace and start of animations.

<div class="timing-function-box"></div>

<style>
  .timing-function-box {
    width: 100px;
    height: 100px;
    background-color: pink;
    animation: timingFunction 4s ease-in-out infinite;
  }

  @keyframes timingFunction {
    0% { transform: translateY(0); }
    50% { transform: translateY(200px); }
    100% { transform: translateY(0); }
  }
</style>

Best Practices for CSS Animations

  1. Minimize CPU Usage: Keep animations simple to avoid excessive CPU usage, which can degrade performance, especially on mobile devices.
  2. Use Hardware Acceleration: Use transform and opacity properties to leverage GPU acceleration.
  3. Fallbacks: Provide fallback styles for browsers that do not support animations.
  4. Performance Testing: Test animations across different devices and browsers to ensure smooth performance.
Info

You may use JavaScript to make more interactive animations. See JavaScript animations.

Example of a Well-Optimized Animation

<div class="optimized-box"></div>

<style>
  .optimized-box {
    width: 100px;
    height: 100px;
    background-color: cyan;
    animation: optimizedMove 3s ease-in-out infinite;
  }

  @keyframes optimizedMove {
    0% { transform: translateY(0) scale(1); }
    50% { transform: translateY(200px) scale(1.2); }
    100% { transform: translateY(0) scale(1); }
  }
</style>

Controlling CSS Animations from JavaScript

CSS handles the rendering of an animation efficiently, but it has no idea when an animation should run or what should happen after it finishes. That decision logic belongs to JavaScript. The most common pattern is: define the animation in CSS, then let JavaScript add or remove a class to start or stop it.

This keeps the smooth, GPU-accelerated playback in CSS while your code stays in control of the timing and follow-up actions.

Starting and Stopping with a Class Toggle

Put the animation on a class instead of the base selector, then toggle that class:

<button id="play">Play</button>
<div id="box"></div>

<style>
  #box {
    width: 100px;
    height: 100px;
    background: teal;
  }
  /* The animation only runs while this class is present */
  #box.run {
    animation: slide 1s ease-in-out;
  }
  @keyframes slide {
    from { transform: translateX(0); }
    to   { transform: translateX(200px); }
  }
</style>

<script>
  const box = document.getElementById('box');
  document.getElementById('play').onclick = () => {
    // Toggle: add the class to play, the CSS animation does the rest
    box.classList.add('run');
  };
</script>

Because the animation lives on the .run class, removing the class instantly stops it and restoring it replays from the start.

Info

Adding and removing animation classes is a styling task. For the full toolkit, read Styles and Classes and Working with Styles in the DOM.

Listening for the End: transitionend and animationend

The key advantage of driving animations from JavaScript is that the browser fires DOM events you can react to. This lets you chain steps, clean up classes, or run code exactly when an effect completes — no fragile setTimeout guessing.

  • For CSS transitions, the transitionend event fires when a transition finishes.
  • For CSS animations (@keyframes), three events fire: animationstart, animationiteration (once per loop), and animationend.
<button id="fade">Fade out</button>
<div id="panel">Hello</div>

<style>
  #panel {
    width: 150px;
    padding: 20px;
    background: gold;
    transition: opacity 0.5s;
  }
  #panel.hidden { opacity: 0; }
</style>

<script>
  const panel = document.getElementById('panel');

  document.getElementById('fade').onclick = () => panel.classList.add('hidden');

  // Runs the moment the fade completes — not a guessed delay
  panel.addEventListener('transitionend', (event) => {
    console.log(`Transition of "${event.propertyName}" finished`);
    panel.style.display = 'none'; // safe to hide only now
  });
</script>

When the transition ends, the console logs:

Transition of "opacity" finished

Reading Event Details: propertyName and animationName

Animation events carry useful data. When several properties or animations are involved, you often need to know which one just finished.

  • event.propertyName — the CSS property that transitioned (on transitionend).
  • event.animationName — the @keyframes name (on the three animation events).
  • event.elapsedTime — seconds of running time, excluding any animation-delay.
<div id="bouncer">Watch the console</div>

<style>
  #bouncer { animation: bounce 0.6s ease 3; }
  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-30px); }
  }
</style>

<script>
  const el = document.getElementById('bouncer');

  el.addEventListener('animationstart', (e) =>
    console.log(`start: ${e.animationName}`));

  el.addEventListener('animationiteration', (e) =>
    console.log(`loop of ${e.animationName} at ${e.elapsedTime}s`));

  el.addEventListener('animationend', (e) =>
    console.log(`end: ${e.animationName} (total ${e.elapsedTime}s)`));
</script>

With animation: bounce 0.6s ease 3 (three iterations), the console logs start, two animationiteration events (loops 2 and 3 begin), then end at 1.8s total.

Warning

animationiteration fires between loops, so an animation that runs N times fires it N − 1 times — never after the final loop. Use animationend for "the whole thing is done."

JS-Driven vs. CSS-Driven: Which to Choose

Use CSS-driven (keyframes/transitions) when…Use JS-driven animation when…
The motion is fixed and declarative (hovers, loaders, entrances).Values depend on runtime data (drag position, scroll, physics).
You want the best performance with the least code.You need frame-by-frame control or to pause/resume mid-flight.
The browser can offload work to the GPU (transform, opacity).You must animate properties CSS can't easily express.

A practical hybrid is the best of both: CSS describes the effect, JavaScript decides when it runs and what happens next via the events above. When you genuinely need per-frame control, reach for JavaScript animations with requestAnimationFrame, or the Web Animations API to build and control animations entirely in code.

Conclusion

CSS animations are a powerful tool for creating dynamic and engaging web experiences. By mastering keyframes, animation properties, and advanced techniques, developers can produce professional-grade animations that enhance user interaction. Experiment with different animations, test thoroughly, and adhere to best practices to achieve the best results.

Practice

Practice
Which of the following statements about CSS animations are correct?
Which of the following statements about CSS animations are correct?
Was this page helpful?