A monolithic style sheet is difficult to reason about, which is challenging as CSS files tend to attract bloat. Removing unused styles can help make the situation more manageable.
Before we start searching for unused styles it’s worth pointing out that there are plenty of other strategies worth utilising to produce well-managed style sheets. We can separate our styles into logical parts (e.g. page layout, buttons, grids, widgets etc) and use sensible naming conventions (e.g. BEM). Developers tend to reach for these before considering unused rules, and I think that’s broadly a good move as they have a lasting impact.
Another reason for the lack of rule pruning is that it is just a bit awkward to find and remove unused styles in anything bigger than a small web project. Unless the content is static, how do we know which rules are used and which are not?
Chrome Developer Tools
It turns out that Chrome developer tools has an applicable feature baked right in. I tried it out on a site that I knew had various style sheet rules that could be removed. The experience was mixed. The barrier to entry is low, especially for developers already used to working with Chrome developer tools. There is nothing extra to install, so that is a bonus.
Steps to audit the style sheet rules for a given site are:
- Navigate to the site in question
- Open Chrome Developer Tools
- Click Audits Tab
- Select ‘Web Page Performance’ option and hit run
Part of the returned results will likely include Remove unused CSS rules
. If this is missing, it means you don’t have any unused CSS rules. Congratulations!
The results are split per style sheet. This isn’t just a point per file, but a point per style
block. Certainly a useful feature, as we only care about the style sheets we are directly responsible for, at least for the purposes of this article.
Is It Any Good?
I couldn’t find a super easy way to export the results out of Chrome. You can copy/paste from the results box, although you’ll need to expand the style blocks you are interested in first. This made sifting through the results a little awkward. Running in a browser like this also pushes us just that bit further away from contact with the code, which probably reduces the number of times we’d remember to go and test the site.
Summary: A useful start, but not a long-term solution.
UnCSS
There are also command line tools available to aid in finding unused style sheet rules. UnCSS is interesting as it fetches your page within phantomJS, with the intention that this will catch styles added by JavaScript. I was keen to give this a go as it solves my complaint about the Chrome audit tool being far away from the code edits. We can use UnCSS and save the results straight out to a file. Ideal.
Installation
My initial npm install uncss
failed on Ubuntu. No major problem, turned out I was missing some dependencies. Commands I ran to install the missing libraries:
sudo apt-get update sudo apt-get install build-essential chrpath libssl-dev libxft-dev sudo apt-get install libfreetype6 libfreetype6-dev sudo apt-get install libfontconfig1 libfontconfig1-dev
Although UnCSS can be integrated into the build process, we’ll skip over that for now. If anything, I’m not sure having this as part of the build process is a good idea. There’s an interesting article on adding this to the build by Addy Osmani, but ideally we want to remove styles we’re not using from our code base, not just filter them out for the final product.
Perhaps the ideal solution is to do both. Firstly, run as a pre-build step to optimise your own code base. Secondly, run as a build step to optimise out the style sheets you don’t have control over.
Command Line Usage
uncss http://your-site.foo/ > unused-styles.css
The output is split per style sheet on your-site.com
as per Chrome, although all the results are lumped into a single file. My sample site used font-awesome and subsequently all the font-awesome icons I didn’t use on the home page appeared in the UnCSS output. For now, I don’t care about these. These can be hidden by running the command again and specifying ignoreSheets
.
Note that ignoreSheets
can take a string (full URL of style sheet to ignore) or a regex. A regex is likely the easier option, as it’s less typing and can cover changes in the path to file etc.
--ignoreSheets /.*font-awesome.min.css/
The regex must be supplied enclosed in forward slashes, as this is how UnCSS checks to see if the argument is a string or not.
Sporadic Errors?
(node:20557) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Network Error
This rather opaque error message was the result of the page timing out. You can specify a longer timeout using -t N
, where N
is the number of milliseconds (so don’t do -t 360
and wonder why it doesn’t wait a full 5 minutes).
Summary: UnCSS feels more convenient, being closer to the point where I would edit a style sheet. The output file can be nothing but useful if you exclude those style sheets you aren’t interested in. I could see the utility in having an --includeSheets
option that auto ignores everything not matching a certain regex. That could be useful for say WordPress sites, where various plugins might pull in their own style sheets, but the developer is only interested in theme style sheet, style.css
etc.
Which Tool?
I initially preferred UnCSS and the command line convenience. However, since drafting this article I’ve tried this out on a few more sites and had less promising results. Most notably, I have several sites built a few years ago that made use of a framework that implements persistent comments using the /*!*...*/
notation. This doesn’t play nicely with PostCSS and thus UnCSS. I haven’t dug into the issue further, potentially a newer PostCSS script is more forgiving of this type of comment, but for now it’s another barrier stopping UnCSS becoming a more common part of my workflow.