Ways You Need To Tell The Browser How To Optimize

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 at 100vw wide.
  • If the browser window is between 30em and 50em, I'll be displaying the image at 50vw 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?