An Introduction to the CSS will-change Property

Share this article

In this article, we’re going to take a look at the CSS will-change property, what it is, when and how to use it, and how not to use it. There’s quite a bit of technical documentation available with regards to will-change, so I’ll reference a lot of those resources throughout this article, and compile them in a list at the end. This article will serve as an overview of the important parts with some quick examples.

Some Background

Today many front-end developers are leveraging CSS3 transitions, transforms, and animations to add a new layer of application interactivity that was previously left up to JavaScript libraries or Flash. Now we’re able to perform smooth and beautiful animations with minimal CSS. If you’ve been experimenting with and utilising these CSS3 properties, you’ve likely come across the terms CPU, GPU, and hardware acceleration. Let’s break these terms down quickly:

  1. The CPU, or the Central Processing Unit, is the piece of hardware that processes pretty much every computer operation. It’s otherwise known as the motherboard.
  2. The GPU, or the Graphics Processing Unit, is the piece of hardware associated with processing and rendering graphics. The GPU is designed to perform complex graphical computations and offloads some serious process weight from the CPU.
  3. Hardware acceleration is a general term for offloading CPU processes onto another dedicated piece of hardware. In the world of CSS transitions, transforms, and animations, it implies that we’re offloading the process onto the GPU, and hence speeding it up. This occurs by pushing the element to a layer of its own, where it can be rendered independently while undergoing its animation.

How does this improve the performance and quality of animations? Well, for starters, on WebKit-based browsers, we may often see a flicker when performing some CSS operations, namely 2D transforms and animations. In the past, we’ve gotten around this by tricking the browser a little. We would make the browser thing it was performing a 3D transform, thus offloading the operation onto the GPU. That’s because 3D transforms are automatically moved there. That leads us to some trickery like this:

.accelerate {
  -webkit-transform: translate3d(0, 0, 0);
}

There are some similar tricks, but for the most part, this covers us. However, this is a hack, and this is where the will-change property will help us out greatly, when used correctly. Let’s investigate.

What is will-change?

According to the W3C editor’s draft:

The will-change CSS property … allows an author to inform the UA ahead of time of what kinds of changes they are likely to make to an element. This allows the UA to optimize how they handle the element ahead of time, performing potentially-expensive work preparing for an animation before the animation actually begins.

This means that instead of forcing our transforms onto the GPU via a 3D transform hack, we can now use a dedicated property to inform the browser to look out for changes in the future, and optimise and allocate memory accordingly. Sounds pretty neat, right? Before we get all excited though, we need to understand how to use will-change.

How is will-change used?

The will-change property is only effective when used at a certain time. We can’t apply something like will-change: transform to an already-transforming element — it just doesn’t make sense. Sara Soueidan discusses this in fantastic detail on the Opera blog, so be sure to check that out, but the key points to note are these:

  1. We’re interested in using this property to let the browser know ahead of time what changes on an element can be expected.
  2. This allows the browser to make the proper optimizations in advance, ultimately leading to quicker and snappier rendering.
  3. As mentioned before, the browser needs to know ahead of time what changes will occur. This means that we have to think in advance when to prepare the browser for the change.

With the above points in mind, let’s look at an example that will have no effect:

.will-change:active {
  will-change: transform;
  transition: transform 0.3s;
  transform: scale(1.5);
}

Here, a change is already taking place by the time we inform the browser, totally cancelling out the whole point of the will-change property. If we want the browser to know ahead of time when to expect changes, we will have to inform it at the right moment.

For an element to achieve an active state, it must first be hovered. We can then do something like this:

.will-change {
  transition: transform 0.3s;
}

.will-change:hover {
  will-change: transform;
}

.will-change:active {
  transform: scale(1.5);
}

This small example gives us some insight into the thought process needed to properly use the will-change property. But before we continue with more examples, we need to be aware of some important considerations.

Browsers, by nature, try their absolute best to optimise and be prepared for changes. Browsers will remove certain optimizations as soon as they can in order to free up memory. Using the will-change property directly on an element, though, insists to the browser that the element in question is always very close to a change. This forces the browser to maintain optimizations, thus increasing memory consumption. With that in mind, we need to have a way of adding and removing the will-change property at the right times. The first example does this for us, because the property will only get added on hover. But what if we wanted the transform to actually occur on hover? You might be tempted to do this:

.will-change {
  will-change: transform;
  transition: transform 0.3s;
}

.will-change:hover {
  transform: scale(1.5);
}

This will result in an increase in memory consumption though, because we’re forcing the browser into thinking that the element is close to being changed at all times. We can get around this by instead looking for a hover event on the parent container:

.will-change-parent:hover .will-change {
  will-change: transform;
}

.will-change {
  transition: transform 0.3s;
}

.will-change:hover {
  transform: scale(1.5);
}

This adds the optimization when the mouse enters the parent container, and removes it when the mouse leaves. It also, however, implies that every time the mouse enters the parent container, the browser can expect a change on the element. This isn’t necessarily the case, and presents a perfectly clear example of how easy it is to abuse this property.

Building a full-screen slideshow or CSS flip-book of some sort is an example of when direct application could work. Slides will always need to be changed, so doing something like the following might be suitable:

.slide {
  will-change: transform;
}

Always Remove will-change

Always remember to remove the will-change property when you’re finished using it. As I mentioned above, browser optimizations are a costly process and so when used poorly they can have adverse effects. We can handle this with JavaScript, and we’ll reference a script from MDN to build a rough case example. Imagine we have an element with a class of element, and when we click on it, it gets transformed. Our CSS could look like this:

.element {
  transition: transform 0.5s;
}

.element.clicked {
  transform: scale(1.5);
}

If we want to notify the browser to prepare optimizations for a change that’s about to happen in response to a click on an element, we can do something like this:

var el = document.querySelector('.element');

el.addEventListener('mouseenter', hintBrowser);
el.addEventListener('animationEnd', removeHint);

function hintBrowser() {
  this.style.willChange = 'transform';
}

function removeHint() {
  this.style.willChange = 'auto';
}

Of course, you’d need to include the necessary JavaScript to add the correct clicked class when the element is actually clicked, but the above script should give you some insight into how to prepare the browser for changes, and to release memory once the changes are complete. When the mouse enters the element, the will-change property is added. When it’s clicked and the transform occurs (by your corresponding script), animation events will be sent out. On animationEnd we’ll remove the will-change property, freeing up memory once again.

Browser Support

The will-change property is fairly new, and is currently supported by the following browsers according to Can I Use:

  • Chrome 36 and up
  • Firefox 36 and up
  • Opera 24 and up
  • Android browser 37
  • Chrome for Android 40
  • Opera Mobile 24

Internet Explorer is the only major missing browser and will-change is listed as under consideration as of this writing.

Final Notes and Sources

The CSS will-change property can do just as much good as it can harm. This statement isn’t meant to deter you from using it, but acts as an advisory. There’s no reason to not consider it in your modern application builds, but just be mindful of all the potential issues I’ve pointed out. I hope you gained some insight into the wild world of browser optimizations, and can take this knowledge forward into your future projects.

There are a few articles that get into some detail about hardware acceleration and the will-change property. I recommend reading up on them as well to firm up your understanding of this umbrella of CSS.

Nick SalloumNick Salloum
View Author

I'm a web designer & developer from Trinidad & Tobago, with a degree in Mechanical Engineering. I love the logical side of the web, and I'm an artist/painter at heart. I endorse progressive web techniques, and try to learn something every day. I try to impart my knowledge as much as possible on my personal blog, callmenick.com. I love food, I surf every weekend, and I have an amazing creative partnership with fellow mischief maker Elena. Together, we run SAYSM.

browser optimizationcss will changelearn-advanced-cssLouisLwill change
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week