In the past few years, there has been a number of front end features in which the performance onus has shifted from browser to developer. Rather than the presumed “browsers will get faster at running my code”, there is a little more “I need to change the way I code for browsers to get faster.”
will-change
Spec:
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.
In other words, in addition to using animations and transforms, tell the browser what you are going to change within those animations and transforms.
.element {
will-change: transform;
}
.element:hover {
transform: rotateY(180deg);
}
Sara Soueidan has a more in-depth article and we have an almanac reference.
contain
Spec:
The contain property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree. This allows user agents to utilize much stronger optimizations when rendering a page using contain properly, and allows authors to be confident that their page won’t accidentally fall into a slow code path due to an innocuous change.
In other words, if you know certain things about an element and its descendants, you should tell the browser so it can optimize around those things. For example… contain: size;
– “This ensures that the containing element can be laid out without needing to examine its descendants.”
Example:
<section class='message'>
Lol, check out this dog: images.example.com/jsK3jkl
</section>
<section class='message'>
I had a ham sandwich today. #goodtimes
</section>
<section class='message'>
I have political opinions that you need to hear!
</section>
.message {
contain: strict;
}
Michael Scharnagl recently wrote a post on this:
Much like an iframe, this boundary establishes a new layout root, ensuring that DOM changes in the sub-tree never trigger reflows in the parent document.
Responsive Images
Perhaps the most visible of these “you tell the browser what’s up” scenarios is responsive images, and particularly the sizes attribute.
Spec:
The user agent will calculate the effective pixel density of each image from the specified w descriptors and the specified rendered size in the sizes attribute. It can then choose any of the given resources depending on the user’s screen’s pixel density, zoom level, and possibly other factors such as the user’s network conditions.
Here’s an example from the spec, where you’re giving the browser as much as you can to work with:
<img
sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)"
srcset="swing-200.jpg 200w, swing-400.jpg 400w, swing-800.jpg 800w, swing-1600.jpg 1600w"
src="swing-400.jpg"
alt="Kettlebell Swing"
>
Which says…
- If the browser window is narrower than
30em
, I’ll be displaying the image at100vw
wide. - If the browser window is between
30em
and50em
, I’ll be displaying the image at50vw
wide. - Otherwise (if it’s even bigger), I’ll be displaying the image at
calc(33vw - 100px)
wide.
Which then needs to match up with what you actually do in the CSS. Hopefully it’s fairly accurate, so the browser optimizations match up with reality.
A Brave New World
I mention these things not because I think you need to run out and start using all this immediately. More to spotlight the (if I may) trend, in front end performance-related features in which the browsers ask more of authors.
I think the browser vendors and spec authors would say: “You want performance. There is only so much we can do. There are certain things we can’t know, but you do know. We’ll do our best without them, but if you tell us about them we can do much more.”
What say you?
In the will-change scenario, I wonder why browsers can’t determine this automatically. Couldn’t a browser read the :hover rules for an element to see if there are any transforms on it?
how’s the browser supposed to know if you dynamically add one of these classes?
&.class1 {
transform: translateX(50%);
}
&.class2 {
box-shadow: 5px 5px 5px red;
}
&.class3 {
background: saddlebrown;
}
Browsers can determine it, more or less. That’s why you shouldn’t use it this way.
will-change property should only be added dynamically by js, just before you trigger a change – otherwise it’s gonna be more or less useless for the browser.
Right before? No. Beforehand right in CSS – yes.
Hi Chris
why not include the group of properties
*-rendering
?:Text-rendering
Image-rendering
and perhaps with less effect
Shape-rendering
Color-rendering
I think they also help.
If this is where we are today in web development, then something has gone wrong. In the vast majority of cases the browser has enough information by parsing the document to know our intentions. Browsers should not need to be micromanaged.
Exactly that.
I think you’re both right and wrong.
Yep! It does! For example, there is enough information to figure out how large to display an image once the HTML is downloaded and parsed to find the image, then the image is downloaded, then all the CSS is found and downloaded, then layout happens, not just to the image itself but to everything around it that might affect its size. Once all that happens, the browser knows enough information to pick the perfect size image for the job. But (oh shit), we’ve already downloaded the image, so we’ve lost the opportunity to optimize.
The trick is to give the browser for information as it’s “parsing the document” so it can make smarter choices sooner.
It certainly feels weird though. Like can’t computers just optimize what I’m giving it? The answer is that it can, but it can be ever better if we help it, especially when we’re specifically working on squeezing out better performance.
You are right. But the browser can not know the changes done by js. For pure css it would be sad if we have to use it.
Patrick from frontend gmbh
The new ones are
requestIdleCallback
and passive event listeners .Nice article (again). Never heard of this before…
Alas, there is a small typo: “if you know certain things about and element” should be “if you know certain things about an element”
Cheers.
A lot is changing in web designing , and these changes are really good
I think it’s great that we can help the browsers optimize our code. Of course, they should still try to work out some optimizations on their own, but I still know better than any browser how my HTML tree will change, so leaving these hints is going to be a fairly useful tool to get that extra performance boost when needed.
Everything is changing,and much better. isn’t?