Skip to content

Illustration by unDraw

Restart a CSS Animation With JavaScript

Restarting a CSS animation with the use of the layout (aka reflow) browser process.

Restarting an animation is not as easy as I originally thought, by just adding and removing classes.

Making this work was more tedious than I originally thought :/

Complex CSS animations can be a pain in the neck as there is no real way of debugging them and, if you have ever mixed them with some JavaScript special sauce, you have surely been in my place.

Yes, that frustrating place where no developer wants to go. To have absolutely no idea how to fix it after trying everything with long hours of researching and debugging.

If you are reading this, you are a web developer and you know what I mean. But worry no more my friend! In this article, I will show you a simple fix to use and properly restart a CSS animation, so your cool animations stay cool.

But first, let me ask you a couple of questions to make sure you are reading the right article and not wasting your time.

Are You:#

  • Trying to synchronise CSS animations on various elements?
  • Restarting an animation on a user event? (e.g. restarting a button's animation on hover or on click events)

If you answered “yes” to at least one of them, this article is for you and hopefully you will find it useful.

So, after having been in that horrible situation a number of times, my drive for curiosity and determination to end those never-ending times of staring at a screen, I have gathered a few possible fixes for properly restarting an animation.

However, I will present you with the simplest and easiest one to add to your code. Without further ado, let’s get right into it.

Removing and Adding the Class Won’t Do the Trick#

Removing and adding the class won’t do the trick. Sorry.

But you were close! So close indeed, that you are missing only a single magic line of code.

void element.offsetWidth;

However, to understand why this line will fix the issue, we will first have to make sure we know what a DOM reflow or layout is.

DOM reflow#

Simply put, the DOM reflow is a user-blocking operation that computes the layout of the document. A reflow on an element is the calculation of its dimensions and position in the document.

There are many ways in which you can trigger a DOM reflow operation in the browser. For an exhaustive list, check out this gist.

For the sake of simplicity, I will show you only one way but feel free to choose anything that is most suitable for your needs.

Performance Danger ahead#

And here comes great responsibility! Bear in mind that the DOM reflow can be an expensive operation, requiring a lot of CPU power and, because it is a blocking operation, it can cause unwanted, bad user experience.

Make sure that you minimise reflow/layout events throughout your website. Knowing more about it and knowing how to control it will make you a true dev ninja.

Now, back to my point. What makes reflow useful for restarting CSS animations is the process during this calculation, which updates the properties of the elements in the DOM and they are then reinitialised.

Meaning, the animation will run again like it’s the first time the animated element has been rendered.

Cool! Now let’s see how and when we can trigger a reflow event inside our JavaScript code.

Triggering a DOM Reflow#

We can simply trigger a DOM reflow by requesting the element’s width or height:

  • Vanilla JavaScript
void element.offsetWidth;
// or similarly
void element.offsetHeight;
  • jQuery
$("#element").width();
// or similarly
$("#element").height();

Why void? Because we don’t care about the returned value, we just want to request the element’s dimensions which will trigger a reflow event.

Restarting a CSS Animation#

For properly restarting your CSS animation, you would ideally like to trigger a reflow event between removing and adding your CSS classes triggering the animation, as shown below:

  • Vanilla JavaScript
var element = document.getElementById("element"); 
element.classList.remove("animate"); 

// trigger a DOM reflow 
void element.offsetWidth; 

element.classList.add("animate");
  • jQuery
$("#element").removeClass("animate");

// trigger a DOM reflow
$("#element").width();

$("#element").addClass("animate");

This instructs the browser to recalculate an element’s width, thus causing a reflow in the DOM. The reflow event triggers the animation to run from the start.

Best practise: I would recommend triggering the reflow as higher up the tree as possible to minimise subsequent reflows that might be triggered on children elements.

Conclusion#

I hope you had a great read and found the fix you were looking for. Let me know if this was useful to you and any other cool ways you are using to fix this issue.

I barely touched the DOM reflow/layout thing, so if you are interested in learning more about how to minimise it check out my other article, Web Performance: Minimising DOM Reflow/Layout Thrashing.

Have a good day!