CSS Performance Properties: Know When to Reach for Them
CSS ships with a handful of properties whose stated purpose is performance, and I confess they sit in a blind spot for me. will-change is a prime example. The name is self-explanatory: you're signaling to the browser that some property — or scroll-position, or the element's content — is about to change:
.el {
will-change: opacity;
}
.el.additional-hard-to-know-state {
opacity: 0;
}
What that triggers, as I understand it, is the browser moving the element's rendering and painting work over to the GPU rather than the CPU. Think of it as the modern, intentional equivalent of the old transform: translate3d(0, 0, 0); hack. In the snippet above, though, it's not obvious that it would matter. opacity is one of the cheapest properties to animate, so the benefit of a will-change hint there seems marginal — unless it makes a real difference only on certain browsers or devices, which is entirely plausible in front-end development.
Around 2014 and 2015, a wave of articles on will-change surfaced, warning about side effects like unexpected stacking context changes and cautioning against overuse. The prevailing advice was to avoid putting this property directly in stylesheets and instead apply it via JavaScript right before a state change, removing it once it's no longer needed. Whether any of that guidance still holds in 2022 deserves a proper deep dive, not a gut feeling.
The One-Line Fix That Changed Everything
While will-change remains something I'd call a "there if you need it" tool, contain is another feature I only half-grok. The property tells the browser that an element won't affect — or be affected by — the layout or style of anything outside itself, which opens the door for optimization. A striking example of its power comes from Johan Isaksson's account of fixing scroll lag on Google's data grid, a problem that surfaced when displaying 500 rows instead of the default 10:
So, what did I do? I simply added a single line of CSS to the
<table>on theElementspanel, specifying that it will not affect the layout or style of other elements on the page.
table {
contain: strict;
}
The reported result was a 10x improvement in scrolling performance. A single declaration achieving that kind of gain is hard to ignore, yet my brain still doesn't automatically reach for contain when building components. That's a gap worth closing, because clearly the interfaces I build are not as fast as they could be.
One More Tool in the Same Family
There's a third property in this cluster: content-visibility. The closest I've come to understanding it was watching Jake and Surma's video where they combined it with contain-intrinsic-size and some carefully chosen magic numbers to dramatically speed up a long page. What hasn't stuck is the practical judgment — when exactly should a typical page apply this?
All three raise the same underlying question: are these properties stopgap measures for fixing measured performance problems, or are they baseline modern CSS that should inform how you write every component? The premature-optimization argument says ignore them until something is visibly slow. But that stance assumes you're stress-testing on the lowest-end devices, and few of us are. The alternative view is more persuasive: if you're building an element that you know won't change in certain ways, contain is the right call; if you know it will change, telling the browser in advance with will-change is simply good communication. And if you're building a section that's always below the fold, letting the browser skip painting it with content-visibility is just sensible.
The honest answer is that these properties are neither purely reactive tools nor everyday defaults like padding. The right time to use them isn't always obvious, but the potential payoff — from a single line of CSS — makes them worth understanding before you need them.



