will-change in CSS

I've been using the will-change CSS property for a while now, but I realized I never understood exactly what it does under the hood.

Below you can see an example of a difference that will-change can make. On the left, you can see the characters and icon move around in an unexpected way when hovered, while on the right, there is no unexpected movement.

no will-change vs will-change example

Safari in particular struggles with this, the difference is very noticeable there.

What Is will-change?

It's a hint to the browser, something along the lines of “hey, I’m about to animate these properties, please get ready.”

Hey, I'm about to animate transform and opacity, please get ready.
Jakub
Ok, cool. I'll see what I can do.

Browsers may respond by promoting the element to its own GPU compositing layer, pre‑allocating memory, or doing nothing at all if they decide the hint isn’t worth it.

Why Does It Matter?

To understand why will-change exists, we first need to understand how browsers render anything on screen. It generally follows these three steps.

Layout

The browser figures out how big every box is and where it sits. Imagine laying out pieces on a board game. This step is mostly CPU work.

Paint

Now the boxes get filled with pixels, colors, borders, shadows and images. Think of someone coloring in the board game pieces. This also uses the CPU and some extra memory to store the painted bits.

Compose

Finally, the painted layers are handed to the GPU, which stacks them together and shows the combined frame on screen like sliding finished drawings under a sheet of glass and moving them around. This step is GPU-heavy.

If an animation touches only compositor friendly properties like transform and opacity, the browser can skip layout and paint and let the GPU handle everything in the compositing step.

Main Layer - CPU
Other Elements
Compositing Layer - GPU
Element with will-change

When you apply will-change, you’re telling the browser that certain properties are likely to change soon. If the browser agrees that it’s worth it, it may promote the element to its own compositing layer.

How Does It Work In Practice?

Without the hint, the browser promotes the element to its own layer only when the animation starts. That one-time layer promotion can cause a tiny stutter in the first frames of the animation.

.animated-button {
  transform: translateX(0px);
  transition: transform 0.3s;
}
 
.animated-button:hover {
  transform: translateX(24px);
}

With will-change, the browser can now pre‑promote the element when the page is idle, so when you hover over the button, the animation is smooth from the first frame.

.animated-button {
  will-change: transform;
  transform: translateX(0px);
  transition: transform 0.3s;
}
 
.animated-button:hover {
  transform: translateX(24px);
}

Usage

If used correctly, will-change can smooth out animations, reduce CPU usage and improve the performance of animations.


However, it’s not free. Creating and maintaining extra layers costs memory and can hurt performance if overused. That's why will-change should be used intentionally and sparingly.

/* Good - only on elements that will actually animate */
.animated-button {
  will-change: transform;
}
 
/* Bad - on every element */
* {
  will-change: auto;
}

You should also specify what the changing properties are going to be. It's very similar to transition-property, as for most use cases you'd avoid using transition-property: all.

/* Good - specifying exactly what will change */
.animated-button {
  will-change: transform, opacity;
}
 
/* Bad - too broad */
.animated-button {
  will-change: all;
}

Properties

In practice you can add any valid CSS property to will-change but there are only a handful that really make a difference.


Those include transform, opacity and filter effects like blur or brightness. Modern browsers also handle clip-path and mask fairly well. For these, the browser can move around the GPU without repainting.

transform
opacity
filter
clip-path
mask
scroll-position
contents

There is also scroll-position, which is great for when you're only animating scroll offset.

.parallax-wrapper {
  overflow: auto;
  will-change: scroll-position;
}

And contents, which tells the browser that the things inside the container will update a lot, but the outer container itself won't move.

.virtual-list {
  contain: content;
  will-change: contents;
}

Other properties such as top, background, border, etc. are legal to write, but don't actually speed anything up except ask the browser to reserve extra memory for no real gain.

Conclusion

will-change is pretty powerful when it comes to animations of all kinds. However, it's not a magic performance switch, it's more of a heads-up.


It won’t fix fundamentally expensive animations. Modern browsers are already very good at optimizing rendering on their own.

will-change

But when used thoughtfully and sparingly, it can make complex animations feel noticeably smoother, and prevent unexpected movement during animations.

More

In case you have any questions reach me at jakub@kbo.sk, see more of my work on Twitter or subscribe to my newsletter.

Newsletter

I share stuff that I'm working on, new posts and resources here.

PreviousOutline OrbitNextAnimated Collection Preview