will-change 4w2uw
The will-change property allows you to inform the browser ahead of time of what kinds of changes you are likely to make to an element in order to allow the browser to optimize how it handles the element ahead of time. 1e395h
Using will-change
, you allow the browser to prepare for certain changes that are likely to take place in the future, ahead of time. This allows it to make appropriate optimizations to render the page more quickly when these changes occur, therefore avoiding a non-trivial start-up cost which can have a negative impact on the responsiveness of a page. This way, when the actual change happens, the page updates in a snappy manner.
For example, when using CSS 3D transform is the only thing that changes between frames, and often provides significant speed benefits.
However, setting up the element in a fresh layer is a relatively expensive operation, which can delay the start of a transform
animation by a noticeable fraction of a second.
In order to avoid this delay when using CSS Transforms and other CSS operations, we have long used translate3d
) to promote elements to their own layers, thus achieving hardware-accelerated operations that run smoother and faster without glitches. However, this technique — also known as “The translateZ()
(or translate3d()
) Hack” — comes with a cost. Paul Lewis has written a very informative post about this that you should definitely check out if you use this technique. will-change
is here to allow us to optimize our animations without having to resort to this hack — or any other hack, for the matter.
You can declare to the browser your intention to change an element’s scroll position, its contents, or one or more of its CSS property values by specifying the name of the properties you’re expecting to change, comma-separated. Most properties will have no effect when specified, as the agent doesn’t perform any special optimizations for changes in most properties. It is still safe to specify them, though; it’ll simply have no effect.
If you expect or plan to change multiple values/aspects of an element, you can provide a list of comma-separated values. A list of comma-separated values can include predefined keywords and/or property names. (See the Examples section below.)
If any non-initial value of a property you’re declaring would create a stacking context on the element, specifying that property in will-change
must create a stacking context on the element. For example, setting opacity
is currently still equal to 1.
Similarly, if any non-initial value of a property would cause the element to generate a containing block for fixed-position elements, specifying that property in will-change
must cause the element to generate a containing block for fixed-position elements.
The will-change
property has no direct effect on the element it is specified on, beyond the creation of stacking contexts and containing blocks as mentioned earlier — it is solely a rendering hint to the agent, allowing it set up potentially-expensive optimizations for certain types of changes before the changes actually start occurring.
That being said, it is important that you know that this property should be used with caution. Different browsers can use the information from will-change
in different ways, and even a single browser might use it in different ways at different times. Overusing it may result in ignoring the declaration altogether. For example, a browser that promotes elements to their own “GPU layer” when they have will-change: transform
specified might avoid doing that when there are too many elements declaring that, to avoid exhausting GPU memory.
Moreover, will-change
shouldn’t be used unless an element is known or expected to change in the very near future (e.g within a fraction of a second). Once it is not needed anymore, it should be unset:
Set
will-change
to the properties you’ll actually change, on the elements that are actually changing. And remove it when they stop.—Tab Atkins Jr. (Spec Editor)
The optimizations that the browser makes for changes that are about to occur are usually costly and, as we mentioned earlier, can take up much of the machine’s resources. The usual browser behavior for optimizations that it makes is to remove these optimzations and revert back to normal behavior as soon as it can. However, will-change overrides this behavior maintaining the optimizations for much longer than the browser would otherwise do.
As such, you should always to remove will-change after the element is done changing, so the browser can recover whatever resources the optimizations are claiming.
Setting will-change
via JavaScript allows for more fine-grained control and time for the browser to prepare for a change, and also allows you to unset it as soon as the animation event ends — you wouldn’t be able to do that if will-change
were declared in CSS otherwise. Using JavaScript, you can declare your changes to the browser, and then remove will-change
after the changes are done, by listening to when these changes have finished.
For example, you could listen for when the element (or its ancestor) is hovered, and then set will-change
on mouseenter
. If your element is being animated, you can listen for when the animation has ended using the DOM event animationEnd
, and then remove will-change
once animationEnd
is fired.
// Rough generic example // Get the element that is going to be animated on click, for example var el = document.getElementById("element"); // Set will-change when the element is hovered el.addEventListener("mouseenter", hintBrowser); el.addEventListener("animationEnd", removeHint); function hintBrowser() { // The optimizable properties that are going to change // in the animation"s keyframes block this.style.willChange = "transform, opacity"; } function removeHint() { this.style.willChange = "auto"; }
If you do want to set will-change
in the style sheet to optimize for an element that might change on hover, you may do something like this:
.el:hover { will-change: transform; transform: rotate()...; }
This isn’t particularly wrong, but it isn’t particularly useful either. You need to declare your intention to the browser some time before the change actually happens, not when it happens, in order to give it some time to prepare for the changes and make the needed optimizations. So, in a scenario like this, you can do this:
.el { will-change: transform; } .el:hover { transform: rotate()...; }
Or, you can set will-change
when the element’s container is hovered, because it takes some time for the hover event to reach the element itself, and the browser could then use that time to prepare for the changes on the element itself:
.container:hover .el { will-change: transform; } .el:hover { transform: rotate()...; }
To sum up, to use will-change
with caution, don’t overuse it, and only set it only when you know the element is about to change, and to unset it after the changes are done.
The will-change
property was first named will-animate
, before its name got changed to will-change
.
Paul Lewis created a tool that would allow developers to more readily understand the ramifications of changing their styles. According to the performance ramifications of changing certain properties, you may or may not want or need to set will-change
to hint the browser about the change in those properties’ values. Lewis’ tool is called
Official Syntax 55184y
- Syntax:
will-change: auto | <animateable-feature>#
where:
<animateable-feature> = scroll-position | contents | <custom-ident>
And the hashtag (#) indicates that you can specify multiple animatable-features. Multiple values are comma-separated.
- Initial: auto
- Applies To: all elements
- Animatable: no
Values 584j31
- auto
- This is the default value. It expresses no particular intent. The browser is not notified of any changes and thus does not make any optimizations to cater for any future changes.
- scroll-position
-
Indicates that the author expects to animate or change the scroll position of the element in the near future. The browser will make the appropriate optimizations for this change ahead of time.
For example, browsers often only render the content in the “scroll window” on a scrollable element, and some of the content past that window, balancing memory and time savings from the skipped rendering against making scrolling look nice. A browser might take this value as a signal to expand the range of content around the scroll window that is rendered, so that longer/faster scrolls can be done smoothly.
- contents
-
Indicates that the author expects to animate or change something about the element’s contents in the near future. The browser will make the appropriate optimizations for this change ahead of time.
For example, browsers often “cache” rendering of elements over time, because most things don’t change very often, or only change their position. However, if an element does change its contents regularly, producing and maintaining this cache is a waste of time. A browser might take this value as a signal to cache less aggressively on the element, or avoid caching at all and just continually re-render the element from scratch.
- <custom-ident> (<-ident>)
-
A
<custom-ident>
entry for details). Indicates that the author expects to animate or change the property with the given name on the element in the near future.For example, browsers often handle elements with
transform
as a signal that it should go ahead and promote the element to its own layer immediately, before the element starts to be transformed, to avoid any delay involved in re-rendering the old and new layers.The
<custom-ident>
.Note that most properties will have no effect when specified, as the agent doesn’t perform any special optimizations for changes in most properties. It is still safe to specify them, though; it’ll simply have no effect.
Examples 3e5p5z
The following tells the browser to expect the element’s transform
property to change in order to make the appropriate optimizations ahead of time.
.el { will-change: transform; }
The above will-change
declaration should be added via JavaScript, and then removed or unset (will-change: auto
) once the changes are over.
The following are all possible and valid will-change
values:
will-change: contents; will-change: scroll-position; will-change: opacity; /* multiple comma-separated values */ will-change: contents, transform; will-change: scroll-position, opacity;
Browser k5t66
CSS will-change property 2s3v2d
Method of optimizing animations by informing the browser which elements will change and what properties will change.
W3C Working Draft
ed from the following versions:
Desktop 3n671n
- 36
- 36
- No
- 24
- 9.1
Mobile / Tablet 4q224p
- 9.3
- 66
- No
- 66
- 60