Will Change

Dealing with CSS performance can be quite interesting. Various factors, like what properties we use, can have detrimental effects on the usability of a page.



I noticed that my site, as simple as it is, was having a bit of an issue with the fixed background that I’ve had. The scroll performance just wasn’t as smooth as I wanted it to be. I don’t remember this ever being an issue when I first built the site but browsers change.



I decided to switch the fixed background to a static background and all was right with the world. I doubt anybody even noticed the change.



Of course, not every performance issue is so easy and inconsequential to fix. Issues like box-shadow or scroll-jacking are often considered required on a project to achieve a designed experience.



With more CSS features comes more complexity comes more possibility of introducing performance issues. Browsers recognized that certain CSS features needed to be handled differently in order to be more performant.



For example, transforms—especially in 3D space—could be offloaded to a GPU to be rendered more quickly. It is for this reason that it was discovered that if we force an element into 3D space using translateZ, even if we’re not actually moving it anywhere, we could get the performance gains we desired.



By abusing a property in this way, an expectation is created between browser developers and web developers—and not a good expectation. It’s like using floats for layout. We’re using a feature in a way for which it was never intended.



Browser developers decided to introduce a new property that more directly dealt with the performance issues while also making expectations clearer for web developers.



CSS now has a will-change property that allows us to tell the browser what things are likely to change and thus provide a hint to the browser that it should optimize these things.



The will-change property is normally used by specifying what CSS property is likely to change on this particular element.



.modal {
will-change: transform;
}


In this case, the transform may or may not actually ever be applied to the modal but we’re trying to tell the browser that maybe it will.



In applying this property, however, there’s an interesting side effect.



If we were doing a transform:translateZ(0), the element would create a new stacking context and in some browsers, it’ll put the layer into its own rendering pipeline. Thus, giving us the performance increase we so desire.



Therefore, by applying will-change: transform, the browser will force the new stacking context regardless of whether the transform has been applied or not.



The key thing to note here is that will-change will only create a new stacking context if the property would also create a new stacking context. Since the transform property creates a new stacking context, will-change: transform creates a new stacking context.



If you did will-change: display then no new stacking context would be created because no display property value would create a new stacking context.



Let’s look at another example: opacity. An opacity with a value of 1 doesn’t create a new stacking context but a value less than 1 (like 0.9) does. When will-change is applied, then a new stacking context is always created.



Browser support

Not all browsers have will-change implemented yet. Therefore, due to the behaviour of it creating a new stacking context, you’ll need to specify a CSS property that does create a new stacking context to achieve similar rendering results.



Chances are, if you’re playing with layering elements on a page, you’re already using position and z-index to achieve the proper stacking order and therefore may not ever run into this rather interesting side effect of the will-change property.

 •  0 comments  •  flag
Share on Twitter
Published on March 15, 2016 09:53
No comments have been added yet.


Jonathan Snook's Blog

Jonathan Snook
Jonathan Snook isn't a Goodreads Author (yet), but they do have a blog, so here are some recent posts imported from their feed.
Follow Jonathan Snook's blog with rss.