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!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!