The will-change
CSS property is commonly misunderstood or not used correctly, in this short post I will demystify the property so you can make your CSS animations and transitions as performant as possible.
In a nutshell, the will-change
property is a way to tell the browser ahead of a time which properties and elements are likely to be manipulated. Using this information, the browser can make optimizations before they are needed which can result in a smoother experience.
An example of this would be if we were applying a transform
on an element we could inform the browser of this like so:
will-change: transform;
You can also declare multiple values like so:
will-change: transform, opacity;
will-change
can take four possible values:
The value we’re going to focus on is custom-indent
i.e. transform
, opacity
, etc.
As stated by Mozilla’s MDN, will-change
should be used as a last resort.
If we abuse the usage of will-change
, we will suffer performance hits which is the exact opposite of what we want. If your animations/transitions are smooth and crisp then there is no need to use will-change
. The browser is already making optimizations without the use of will-change
.
A common mistake people make when using will-change
is this:
.my-element:hover {
will-change: opacity;
transition: opacity .25s ease-in-out;
}
This is doing more harm than good, will-change
is future tense so it shouldn’t be applied when the animation is happening.
A better use of will-change
here would be to put the will-change
on the parent of my-element
like so:
.parent-element:hover {
will-change: opacity;
}
.my-element:hover {
transition: opacity .25s ease-in-out;
}
This lets the browser know ahead of time to optimize for this change. Remember to use this as a last resort if your animations are janky or flickering.
It is recommended by Mozilla to remove will-change
after the element is done changing. This is why it’s also recommended to set will-change
via JavaScript so you can remove it. If will-change
is set in the CSS stylesheet, it can not be removed.
Code-wise this is quite simple and looks like this:
const el = document.querySelector('.parent-element')
el.addEventListener('mouseenter', addWillChange)
el.addEventListener('animationend', removeChange)
const addWillChange = () => {
this.style.willChange = 'opacity'
}
const removeChange = () => {
this.style.willChange = 'auto'
}
The code above is very simple, we’re adding our will-change
to the parent-element
when it is hovered then when the animationend
event is fired we then remove our will-change
.
Setting will-change
in a stylesheet can make sense in some circumstances. A circumstance such as this would be an element that is likely to be interacted with multiple times, this could be something like a ripple effect on a button or a sidebar sliding out. Generally, there should only be a handful of will-change
properties in a stylesheet, the rest should ideally be set through JavaScript.
This was a short little introduction to will-change
, and if you’re looking to dive deeper I would really recommend checking out Sara Soueidan’s great article on the topic.
Thanks for reading!
Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.
Sign up