Sluggish Animations On Purpose: Part 1
A sluggish animation developed on purpose. And then, a fix that might surprise you
Why?
I like the idea of breaking things to understand how they work. With physical stuff, it might be dangerous; if you break it, you might lose it forever. Yet, it’s easy to break and fix things with software.
In this article, I want to show a sluggish animation developed on purpose. And then, a fix that might surprise you. We will also go into the details of why the solution works.
Sluggish Animation
I created a website with a box that moves from one place to another.
Then, I added a button, that on click, triggers a long and CPU-intensive calculation in Javascript, making the animation sluggish.
Notice how when the top left button is clicked, the animation stops for a moment.
What’s the Problem?
With this example, we learn that heavy JS executions affect style animations.
We find the answer in the MDN docs:
By default, the browser uses a single thread to run all the JavaScript in your page as well as to perform layout, reflows, and garbage collection.
Solutions
I can think of two different approaches to solve this problem. One involves improving JS execution and the other improving our animation.
In this article, I want to solve it with CSS. In another article, we’ll solve it with Javascript.
CSS Animation
Let’s look at the animation again:
It moves from top left to bottom right. Therefore, we used animations on the “top” and “left” CSS rules.
.box {
// ...
animation: move 3s ease infinite;
}
@keyframes {
50% {
top: (300px - 60px);
left: (300px - 60px);
}
}
How Does the Browser Render the Animation?
The browser renders the website at sixty frames per second. That’s once every sixteen milliseconds. On every frame, the browser might need three different steps: “Recalculate Style,” “Layout,” and “Paint.”
From MDN Docs:
Recalculate Style: every time a CSS property for an element changes, the browser must recalculate computed styles.
Layout: next, the browser uses the computed styles to figure out the position and geometry for the elements. This operation is labeled “layout” but is also sometimes called “reflow.”
Paint: finally, the browser needs to repaint the elements to the screen. One last step is not shown in this sequence: the page may be split into layers, which are painted independently and then combined in a process called “Composition.”
These processes are done at the beginning of every website and after CSS changes. Yet, not all CSS modifications trigger all the steps. This is the exciting part.
For example, properties that affect geometry or positioning trigger all the steps. Whereas properties that are rendered in their own layout trigger only one step. You can find the full table of triggers at this link.
Current CSS Animation
Our current CSS animation is done with “top” and “left,” which are properties that affect the positioning of elements. Therefore, the modifications trigger all the rendering steps.
@keyframes move {
50% {
top: calc(300px - 60px);
left: calc(300px - 60px);
}
}
On the other hand, the “transform” property triggers only one step, making it a much more performant animation.
@keyframes move {
50% {
transform: translate(calc(300px - 70px), calc(300px - 70px));
}
}
This is the video of the animations with “transform” instead of “top” and “left”:
You can see how now, clicking the button, does not affect the animation.
Inspect It
Let’s look at the “Performance” tab in the Dev Tools to see how one animation triggers more steps than the other.
Learn to Break It
I learned a lot by building this broken project from the beginning. Real-world projects are complex, and many pieces are interconnected. Therefore, they are not ideal for learning the principles.
Yet, with a simple project that does only CSS animations, we control all the variables that affect the problem and focus on how one thing works.
Don’t be afraid to break things. And build to learn and try things.
Resources
MDN Docs: Animation CSS Properties.
CSS Triggers: List of CSS rules and the rendering steps that they trigger.
If you like this post, consider sharing it with your friends on twitter or forwarding this email to them 🙈
Don't hesitate to reach out to me if you have any questions or see an error. I highly appreciate it.
And thanks to Michal for reviewing this article 🙏