Here’s the thing about “unused CSS” tools

Avatar of Chris Coyier
Chris Coyier on

There are a lot of tools that aim to help you remove “unused CSS” from your project. Never a week goes by that I don’t see a tool for this being shared or promoted. It must strike some kind of perfect chord for some developers. I care about performance, and I know that reducing file sizes is good for performance. Indeed, it is. I bet we have CSS that is unused in our stylesheets, if we removed that, that’s a performance win. Yep, it would be. We should automate that. Ehhhhhh, I’m not so sure.

There are major performance tooling players that play up this idea, like Lighthouse and how it gives you CSS and JS “Coverage”, which will surely tell you that you’re shipping code you don’t need to be.

The tools that claim to help you with unused CSS have to perform analysis to be able to tell you what is unused and what isn’t.

Here’s one way to do that analysis. Render a page of your site and get the complete DOM. Then get the complete CSSOM as well, which can give you an array of all the selectors in your CSS. Loop over those selectors and do a querySelector in the DOM and see if it matches anything. If it doesn’t, that CSS selector is unused.

Clever, right?!

I think so. But that analysis paints a rather limited picture.

Say that analysis runs two seconds after the page is complete, but there is some JavaScript that runs and injects a modal after five seconds (ughghk, I know). The analysis would have missed the HTML in that modal, which likely has styles, and thus would have incorrectly reported those styles as unused.

So, timing is one factor. Hopefully, this analysis tool has some way to configure multiple timings.

We’re also only looking at one page so far. Of course, a site might have tens, hundreds, or thousands of pages. To be entirely sure about unused styles, looking at all of them is the most sure-fire bet.

Multiple pages is another factor. Hopefully, an analysis tool has a way to look at as many pages as you tell it to. Perhaps it can look at a sitemap?

Remember the timing thing? We might think of timing as one generic form of state. There are countless other things that could be state related. Is the user logged in or not? What plan are they on? Is their credit card expired thus showing some kind of special message? Do situational things like time/date/geolocation change state? What about real-time data? Stuff from an API?

Application-level state is clearly a big factor. Hopefully, this analysis tool can trigger/set all possible combinations of state.

There is interactive state as well. What about modals that come up because something is clicked? What is the active tab? Is this menu open or closed? What scroll position are they at? There are infinite permutations of this. Imagine a warning bar that shows up seven seconds after the user logs in to warn user about their expired credit card which contains a custom styled select menu which can be in an open or closed state, but only on the user settings page.

It seems unlikely that this analysis tool can handle all those possibilities. Even with loads of configuration, mock state, and integration testing, it couldn’t cover the near-infinite possible permutations of all this.

And yet, I don’t think these tools are useless — they are just…tools. Their use can actually be a positive step toward better code. Their use says OK, I admit it, I’m a little afraid our CSS. You could use this tool to get a broad picture of what your unused CSS might be, then combine that with your own knowledge of your CSS code base to make more informed decisions. Or take another technological step and do something like add a background image to those unused selectors and check server logs to see if they get hit.

It should be said that this whole idea of unused CSS is a part of the CSS-in-JS saga that our industry is going through. If all your styles are written as part of components, there kinda is no unused CSS. Either the component gets used and the styles come with it, or it doesn’t. If you’re particularly sensitive about the danger of unused CSS, that alone might sway you toward a CSS-in-JS tool.

It also should be said that this DOM and CSSOM analysis technique is only one possible way of checking for unused styles. If you had some kind of fancy tooling that could analyze all of your templates, styles, and scripts, presumably that could determine unused styles as well. We talk about that in the recent ShopTalk Show episode with Chris Eppstein.