How to Pause and Resume CSS Animations

The CSS animation-play-state property provides native control over the playback of CSS keyframe animations, allowing them to be paused and resumed on demand without resetting their current progress. By switching between its two primary values, running and paused, developers can freeze an animation at its exact frame and later continue playback seamlessly from that identical point in time.

The Core Values

The property accepts two primary keyword values:

  • running: The default state. The animation executes normally according to its defined duration, timing function, and delay.
  • paused: Freezes the animation. The target element remains stationary at the exact visual frame and time offset reached at the moment this value was applied.

How Pausing Works Under the Hood

When a CSS animation runs, the browser tracks its elapsed time and maps it to the keyframe rules defined in @keyframes. If animation-play-state: paused is triggered, the browser immediately stops advancing the internal animation timeline.

Unlike removing an animation class or changing the animation-name—which resets the animation to its starting frame (or default styles)—animation-play-state preserves the element's current computed styles and playback timestamp. The animation’s cycle, iteration count, and direction remain intact. When the state is switched back to running, the animation resumes from the exact millisecond and frame where it was halted.

Implementation Methods

1. Pure CSS (Hover or Focus States)

You can pause animations using CSS pseudo-classes, which is common for elements like rotating carousels, ticker feeds, or continuous background loops.

.animated-box {
  animation: slide 5s linear infinite;
  animation-play-state: running;
}

.animated-box:hover {
  animation-play-state: paused;
}

In this setup, hovering over the element halts the animation, and moving the cursor away resumes it from that specific spot.

2. JavaScript Control

For user-driven events, such as a toggle button, JavaScript can modify the inline style or toggle a class that alters the property.

const element = document.querySelector('.animated-box');

function toggleAnimation() {
  const currentState = window.getComputedStyle(element).animationPlayState;
  element.style.animationPlayState = currentState === 'paused' ? 'running' : 'paused';
}

Handling Multiple Animations

If an element has multiple comma-separated animations applied, animation-play-state can target each one individually by providing corresponding comma-separated values:

.multi-animated {
  animation-name: spin, fade;
  animation-duration: 3s, 1s;
  animation-play-state: running, paused; /* 'spin' runs, 'fade' is paused */
}

If fewer values are provided than there are animations, the browser repeats the list of values to match the total number of running animations.