Here's what I'd like you to know upfront: this is a hard problem. If you've landed here because you're hoping to be pointed at a tool you can run that tells you exactly what CSS you can delete from your project, well... there are tools out there, but I'm warning you to be very careful with them because none of them can ever tell you the complete story.
I know what you want. You want to run the tool, delete what it tells you, and you have a faster site in 2.2 minutes. I'm sorry, but I'm going to disappoint you.
I think you should have a healthy level of skepticism for any tool like that. None of them are exactly lying to you — they often just don't have enough information to give you results that are safe and actionable. That's not to say you can't use them or it can't be done. Let's take a walk.
I imagine the #1 driver for the desire to remove unused CSS is this:
You used a CSS framework (e.g. Bootstrap), included the framework's entire CSS file, and you only used a handful of the patterns it provides.
I can empathize with that. CSS frameworks often don't provide simple ways to opt-in to only what you are using, and customizing the source to work that way might require a level of expertise that your team doesn't have. That might even be the reason you reached for a framework to begin with.
Say you're loading 100 KB of CSS. I'd say that's a lot. (As I write, this site has ~23 KB, and there are quite a lot of pages and templates. I don't do anything special to reduce the size.) You have a suspicion, or some evidence, that you aren't using a portion of those bytes. I can see the cause for alarm. If you had a 100 KB JPG that you could compress to 20 KB by dropping it onto some tool, that's awesome and totally worth it. But the gain in doing that for CSS is even more important because CSS is loaded in the head and is render blocking.
Looking at "coverage"
It tells me that 70.7% of my style.css file is unused. I imagine it's right, and that the rest of the CSS is used elsewhere. I didn't just dump a big style library onto this site; I wrote each line of that by hand, so I have my doubts that more than 2/3 of it is unused globally.
I hate to say it but I find looking at code coverage pretty useless. For me, it paints a dire picture of all this unused code on the site, which preys upon my doubts, but all I can do is worry about it.
This might be the very thing that's given you the idea that unused CSS needs to be discovered and deleted in the first place.
My primary concern
And you go, Perfect! I'll delete that CSS! And you do, only to find out it wasn't unused at all and you caused big styling problems throughout the site. Here's the thing: you don't actually know if a CSS selector is unused unless you:
- check coverage on every single page of your entire site...
- under every possible combination of state...
- in every possible combination of media queries you've used.
Checking your homepage doesn't count. Checking all your top-level pages doesn't count. You gotta dig through every page, including states that aren't always top-of-mind, not to mention all of the edge-case scenarios. Otherwise, you might end up deleting the dropdown styling for the credit card choice dropdown in the pop-up modal that appears for users with a disabled account who've logged in during their grace period that also have a gift card to apply.
This is too complex for automated tooling to promise their approach works perfectly, particularly when factoring in the unknowns of browser context (different screen sizes, different capabilities, different browsers) and third parties.
PurifyCSS Online takes some URLs and instantly provides a copy-pasteable chunk of CSS to use
Perhaps you can see why my trust in these tools is so low.
Part of a build process
So keep that in mind as well. It's dumb in the way it compares potential selector matches, which is both clever and dangerous.
UnusedCSS is an online service that crawls your site for you
Manually configuring a tool to look at every page on your site from every angle is certainly a chore and something that will need to be kept in sync day-to-day as your codebase evolves. Interestingly, the online service UnusedCSS tries to overcome this burden by crawling the site itself based on a single URL you give it.
I signed up for the paid service and pointed it at CSS-Tricks. I admit, with just a glance at the results, it feels a lot more accurate to me:
It also lets you download the cleaned file and offers lots of customization, like checking/unchecking selectors you actually want/don't want (e.g. you see a class name it doesn't think you need, but you know for sure you actually do need it) as well as prefixing and removing duplicate selectors.
I enjoyed the increased accuracy of the online crawling service, but there was a lot of noise, and I also can't see how I'd incorporate it practically into a day-to-day build and release process.
Tooling is generally used post-processing
Say your CSS is built with Less or Sass, then uses a postprocessor to compile it into CSS. You'd probably incorporate automated unused CSS cleaning at the very end of whatever other CSS preprocessing you do. Like...
- PostCSS / Autoprefixer
- [ Clean Unsued CSS ]
- Production CSS
Visual regression testing
You screenshot as much of your site as possible — like all of the most important pages and those pages manipulated into different states — plus across different browsers and screen sizes. Those screenshots are created from your master branch on Git.
Then, before any branches gets merged into Master, you take all those screenshots of them and compare those to the screenshots in master. Not manually, but programmatically.
The relation to Atomic CSS and CSS-in-JS
I'm sure there are lots of people reading this that would say: I don't have unused CSS because the tooling I use generates the exact CSS it needs and nothing more.
Hey, that's kinda cool.
Maybe that's Atomizer. Maybe that's Tachyons that you also run through UnCSS and you are super careful about it. Maybe it's the Tailwind + PurgeCSS combo that's all the rage right now.
How do you avoid unused CSS in future projects?
I think the future of styling is an intentional split between global and componentized styles. Most styles are scoped to components, but there are global styling choices that are made that take clear advantage of the cascade (e.g. global typography defaults).
If most styling is left scoped to components, I think there is less opportunity for unused styles to build up as it's much easier to wrap your mind around a small block of HTML and a small block of CSS that directly relate to each other. And when components die or evolve, the styling dies or evolves with it. CSS bundles are made from components that are actually used.
If all that seems theoretical or out-of-reach, and you just have a Bootstrap site where you're trying to reduce the size of all that Bootstrap CSS, I'd recommend starting by using Bootstrap from the source instead of the final default distributed bundle. The source is SCSS and built from a bunch of high-level includes, so if you don't need particular parts of Bootstrap, you can remove them.