keepcalculator

06 Numbers and Powers

Web Animations API: Reverse a Running Animation

Card No. 06·54650 · Updated · Standard formula, shown below

To reverse a running animation with the Web Animations API, call animation.reverse() on the animation object. This method changes the animation’s playback direction and, if it was paused, resumes it from the current position. If the animation is already playing, it will smoothly reverse from its current progress point.

Background: What Is the Web Animations API?

The Web Animations API (WAAPI) is a browser-native interface that lets you create and control animations directly in JavaScript, without needing external libraries like GSAP or Anime.js. It unifies animations from CSS Transitions, CSS Animations, and JavaScript-driven effects into a single, performant model. You create an animation with element.animate(), which returns an Animation object. That object exposes methods like play(), pause(), cancel(), reverse(), and properties like playbackRate and currentTime.

WAAPI is supported in all modern browsers (Chrome, Firefox, Safari, Edge) and is designed for smooth, compositor-thread-driven animations. It’s a solid choice for interactive UI effects, scroll-triggered animations, and complex choreography that would be cumbersome with CSS alone.

How Reverse() Works Under the Hood

When you call reverse(), the browser performs the following steps:

  1. It flips the sign of playbackRate (e.g., from 1 to -1, or from -1 to 1).
  2. If the animation is paused, it resumes it (sets playState to running).
  3. It keeps the current currentTime as the starting point, so the animation reverses from where it is, not from the end.

This is different from simply setting playbackRate = -1 because reverse() also handles the play state. If you set a negative rate on a paused animation, it stays paused; you’d need to call play() as well.

Here’s a minimal example:

const box = document.querySelector('.box');
const anim = box.animate([
  { transform: 'translateX(0)' },
  { transform: 'translateX(200px)' }
], { duration: 1000, fill: 'forwards' });

// Later, reverse it:
anim.reverse();

After reverse(), the animation will play backwards from its current position toward the start. If it had already finished, it will start from the end and go to the beginning.

How to Choose: Reverse vs. PlaybackRate vs. Restart

You have several options for reversing an animation, and the best one depends on your goal:

  • Use reverse() when you want to flip direction from the current point and also ensure the animation is playing. This is the simplest and most semantic way.
  • Use playbackRate = -1 when you want to reverse the direction but keep the current play state (e.g., stay paused). This is useful for scrubbing or previewing.
  • Use currentTime = 0 then play() when you want to restart from the beginning, not reverse from the current position.
  • Use cancel() and re-animate() when you need to change the keyframes or options entirely.

For a simple toggle (play forward, then reverse), reverse() is usually what you want. But be aware that if the animation is already reversed (playbackRate is negative), calling reverse() again will flip it back to forward. That makes it a natural toggle method.

Common Problems and Pitfalls

Here are frequent issues developers run into when reversing animations with WAAPI:

  • Animation doesn’t reverse because it’s finished: If the animation has fill: 'forwards' and has completed, reverse() will still work, but it will start from the end. If you want it to reverse from the exact visual state, that’s fine. If you want it to reverse from the middle, you need to set currentTime first.
  • Reverse() seems to do nothing: This often happens if the animation is already reversed (playbackRate is -1). Calling reverse() again flips it back to forward. Check anim.playbackRate before calling it.
  • Paused animations don’t resume: Some developers expect reverse() to just change direction, but it also resumes. If you want to reverse while staying paused, set playbackRate = -1 instead.
  • Timing issues with easing: The easing function applies to the direction of play. When reversed, the easing is mirrored, so an ease-in becomes ease-out. This is usually desirable, but be aware if you have a custom cubic-bezier.
  • Multiple animations on the same element: element.animate() returns a new animation each time. If you call it again, you create a second animation. Keep a reference to the original to reverse it, or use element.getAnimations() to find it.

Comparison: WAAPI vs. CSS Animations vs. JavaScript Libraries

How does reversing in WAAPI compare to other methods?

  • CSS Animations: You can reverse a CSS animation by toggling animation-direction: reverse or alternate, but you have to restart it or use a class change. WAAPI gives you programmatic control over the exact current time and direction.
  • GSAP (GreenSock): GSAP has a reverse() method that works similarly, but it’s a third-party library. WAAPI is native and lighter, but GSAP offers more advanced features like timeline control and cross-browser consistency for older browsers.
  • Anime.js: Similar to GSAP, Anime.js has reverse(). WAAPI is more standardized, but Anime.js has a simpler API for complex stagger effects.

For modern browsers, WAAPI is often sufficient and avoids the overhead of a library. For legacy browser support or very complex timelines, libraries still have an edge.

Practical Example: Toggle Play/Reverse Button

Here’s a complete example of a button that toggles an animation between forward and reverse:

<button id="toggle">Reverse</button>
<div id="box" style="width:50px;height:50px;background:tomato;"></div>

<script>
const box = document.getElementById('box');
const anim = box.animate([
  { transform: 'translateX(0)' },
  { transform: 'translateX(300px)' }
], { duration: 1000, fill: 'forwards' });

// Pause initially so the user controls it
anim.pause();

document.getElementById('toggle').addEventListener('click', () => {
  if (anim.playbackRate > 0) {
    anim.reverse();
  } else {
    anim.reverse(); // flips back to forward
  }
});
</script>

In this example, the animation is paused at the start. Clicking the button calls reverse(), which sets playbackRate to -1 and plays it backwards from the current time (0, so it stays at 0). Clicking again flips it to forward and plays from the current time. This is a simple toggle.

Frequently Asked Questions

Does reverse() work on animations created with the Element.animate() method?

Yes, reverse() is a method on the Animation object returned by element.animate(). It works on any animation created via WAAPI, including those from CSS animations if you retrieve them with element.getAnimations().

Can I reverse an animation that is already finished?

Yes. If the animation has completed and has fill: 'forwards', calling reverse() will start it from the end and play towards the beginning. If you want to reverse from a specific point, set currentTime first.

What’s the difference between reverse() and setting playbackRate = -1?

reverse() flips the sign of playbackRate and also resumes the animation if it was paused. Setting playbackRate = -1 only changes the direction; the animation stays paused if it was paused. Use reverse() for a simple play/reverse toggle, and playbackRate for finer control.

How do I reverse an animation from the middle, not from the beginning or end?

Set animation.currentTime to the desired time (in milliseconds) before calling reverse(). For example, anim.currentTime = 500; anim.reverse(); will reverse from the halfway point.

Does reversing affect the easing function?

Yes, the easing function is applied in the direction of playback. When reversed, an ease-in becomes ease-out and vice versa. This is usually the expected behavior, but if you need a specific easing regardless of direction, you may need to adjust it manually.

Is there a way to reverse all animations on an element at once?

Yes, you can iterate over element.getAnimations() and call reverse() on each. For example: element.getAnimations().forEach(anim => anim.reverse());

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →