What the property actually does
will-change: transform tells the browser 'this element is about to animate its transform — promote it to its own compositor layer now, so the animation does not have to do the promotion on the first frame.' That first-frame promotion is exactly where stutter comes from, so the promise removes it.
The cost: a compositor layer is a texture in GPU memory. Ten elements with will-change are ten textures. A hundred — a scroll-linked hero, a staggered grid, every card in a bento — and you have traded first-frame stutter for a memory bill and, ironically, slower scrolling as the GPU fights to keep all those layers alive.
The classic bug is will-change: transform on a hover target that never animates, or left on after the animation ends. The browser keeps the layer alive indefinitely, and the page quietly pays for layers that do nothing. will-change is a promise: when the animation finishes, you must revoke it — or the browser keeps reserving the table for a guest who left.
The rules that keep the promise honest
- Apply will-change in JavaScript right before the animation starts, and remove it in the animationend / finished handler. CSS-only: use it on the :hover state or a class that toggles with the animation.
- Limit it to transform and opacity — the two properties that animate on the compositor. will-change: all is a panic attack, not a strategy.
- Never apply it to more than a handful of elements. If you need dozens of layers, the problem is the layout, not the promotion.
- Never put it on a resting state that does not animate — that is the promise with no event.
- Prefer the browser's own judgment for one-off entrances: most modern engines promote at animation start fast enough that will-change is only needed for long or heavy animations.
el.addEventListener("mouseenter", () => {
el.style.willChange = "transform"; // promise made
el.animate([{ transform: "scale(1.06)" }], { duration: 180 });
});
el.addEventListener("animationend", () => {
el.style.willChange = "auto"; // promise kept & released
});When it genuinely pays
Three cases earn their keep. Long-running animations: a drifting aurora band or a continuous marquee that will animate for seconds, where a missed frame at any point is visible. Scroll-linked effects: an element that must already be a layer when the scroll handler starts writing to it. And many elements transforming simultaneously — a full grid stagger — where the browser would otherwise promote fifty layers in one frame.
Everywhere else, measure first. If the entrance is one card, let the browser do its job. will-change is an optimization you apply to a problem you have measured, not a garnish you sprinkle for luck.