Animations and Performance

Animations that stutter or stall are immediately noticeable and degrade the user experience. The goal is to maintain 60fps while animating. That means understanding the cost of animating a given CSS property, because some properties are far more expensive than others.

Animating properties that change an element's geometry, such as width and height, triggers layout (also called reflow in Firefox). This process can cause other elements on the page to shift or resize. Layout is often followed by paint, which is typically even more expensive. On pages with many elements, these operations can quickly become costly.

To avoid this, limit animations to opacity and transform wherever possible. Modern browsers can highly optimize these properties, whether the animation is driven by CSS or JavaScript. Avoid animating properties that force layout or paint.

Preparing with will-change

Use the will-change property to tell the browser which properties you plan to animate. This lets the browser apply optimizations in advance rather than reacting after the animation starts. Supported in most modern browsers, it helps keep animations smooth.

However, will-change should not be overused. Applying it too broadly waste resources and can create more performance problems. As a rule, enable it on elements that will animate in the near future—within roughly the next 200ms, whether triggered by user interaction or application state. For the box example used in previous guides, the declaration would look like this:

.box {
  will-change: transform, opacity;
}

With will-change in place, supporting browsers handle the required optimizations behind the scenes.

CSS vs. JavaScript

Much has been written comparing the performance of CSS-based and JavaScript-based animations. The key distinction comes down to which thread handles the work:

  • CSS animations, and the Web Animations API where supported natively, typically run on the compositor thread, separate from the main thread where styling, layout, paint, and JavaScript execute. This means expensive main-thread tasks will not interrupt them.
  • In many cases, changes to transform and opacity are also handled on the compositor thread.
  • When an animation requires layout or paint, the main thread gets involved regardless of whether the animation is CSS- or JavaScript-based.