uncss: Find Unused CSS

By  on  

You know what's better than adding features to a website or app, from a code perspective?  Removing stuff you don't need.  Whether it be code, images, or dependencies, getting rid of the crap stale code is like the first sip of a big glass of wine after a long day of stressful work.  Running a directory of images through ImageOptim is a euphoric experience, am I right?  What if there was a tool, however, which would allow you to find unused CSS for a given website?  There is, and it's called uncss, a NodeJS powered utility.  Let's take a look at how uncss works!

A basic usage of uncss's command line tool would be:

uncss https://davidwalsh.name > styles.css

The output of this execution is a stylesheet featuring only the used CSS rules -- unused rules are removed.  So how does uncss work?  I'll let them tell you how:

  1. The HTML files are loaded by PhantomJS and JavaScript is executed.
  2. Used stylesheets are extracted from the resulting HTML.
  3. The stylesheets are concatenated and the rules are parsed by css-parse.
  4. document.querySelector filters out selectors that are not found in the HTML files.
  5. The remaining rules are converted back to CSS.

Like just about every NodeJS-based utility, you can also take advantage of its JavaScript API.  Here's an example usage:

var uncss = require('uncss');

var files   = ['my', 'array', 'of', 'HTML', 'files'],
    options = {
        ignore       : ['#added_at_runtime', /test\-[0-9]+/],
        media        : ['(min-width: 700px) handheld and (orientation: landscape)'],
        csspath      : '../public/css/',
        raw          : 'h1 { color: green }',
        stylesheets  : ['lib/bootstrap/dist/css/bootstrap.css', 'src/public/css/main.css'],
        ignoreSheets : [/fonts.googleapis/],
        urls         : ['http://localhost:3000/mypage', '...'], // Deprecated
        timeout      : 1000,
        htmlroot     : 'public'
    };

uncss(files, options, function (error, output) {
    console.log(output);
});

/* Look Ma, no options! */
uncss(files, function (error, output) {
    console.log(output);
});

/* Specifying raw HTML */
var raw_html = '...';
uncss(raw_html, options, function (error, output) {
    console.log(output);
});

There's no arguing that years of maintaining, adding, and removing from a site will add excess code to the codebase.  That excess code comes at the cost of users who have load the extra code, so eliminating the dead code is important.  Give uncss a try -- it's an easy to use, automated helper to keep your codebase as tight as possible!

Recent Features

  • By
    Convert XML to JSON with JavaScript

    If you follow me on Twitter, you know that I've been working on a super top secret mobile application using Appcelerator Titanium.  The experience has been great:  using JavaScript to create easy to write, easy to test, native mobile apps has been fun.  My...

  • By
    Facebook Open Graph META Tags

    It's no secret that Facebook has become a major traffic driver for all types of websites.  Nowadays even large corporations steer consumers toward their Facebook pages instead of the corporate websites directly.  And of course there are Facebook "Like" and "Recommend" widgets on every website.  One...

Incredible Demos

Discussion

  1. This looks awesome David, gunna give it a whirl tonight and see what gaping hue holes there are lol

  2. Does this take into account prefixes? If so, this would make a great addition to my Grunt builder!

  3. If you’re in the browser, you can use Google Chrome for this. Open the Web Dev tools, Click on the Audits tab, click Run, and then look through the “Remove unused CSS rules” list.

    Only for a single page though.

    • Which if you have more than 4 or 5 pages on a site, is a true pain in the arse.

  4. Slightly different, but I have always used “Dust me selectors”, its a browser plugin that helps to find and build a list of unused selectors.

  5. Does this work for a single page ? Or for the entire website. Because there may be few styles that are written in a common .css file but of which say 40 lines of css are written exclusively for page 1 and 20 lines of css exclusively for page 2.

    Is that handled ?

  6. I also use Dust-Me Selectors in Firefox. You can crawl your whole site supplying it with a sitemap.

    While these housekeeping tasks of clearing out images, js, css, have lower priority for many, it would be handy to have a sophisticated solution to make it easy to maintain overall

  7. how does this handle a CMS (such as WordPress) with dynamically generated URLs?

  8. What about class names that are added dynamically using javascript? If it filters out rules that are not being used in the initial HTML load then any user actions which cause class name changes will loose their styles as they will be filtered out.

  9. Very useful Nodejs utility. Let me add in my workflow with Gruntjs. Thanks David!

  10. Mick

    I’m with Norcross. This sounds like a fantastic tool, and works well in my tests on static html, but what about WordPress?

    I’ve search high and low for a solution for this, the closest I have come is suggestions to use PhantomJS in tandem with UNCSS, but no further explanation.

    It was my understanding that uncss was already using phantomjs to find all the unused selectors, so how does one crawl a dynamic site?

  11. srigi

    Nice tool, I’m considering to use it in future. However I have two practical questions:

    1. How to use this on responsive sites? This tool will definitely return different sets of styles when run in for example xsmall & large screen mode. There must be some kind of login on the server, that provide correct styles for the device, or some kind of merge of different styles sets.

    2. What then? Everybody is proposing this new coolnes, but nobody is blogging what to do after. Should I load full CSS asynchronously? Or should I put before ending ? Or should I do diff between uncss & full CSS and load this diff?

  12. srigi

    *Or should I put <link rel=stylesheet>before ending <body>?

    • Greg Davis

      Check out this post for WordPress integration:
      http://www.shamimeboodhoo.com/using-grunt-uncss-with-wordpress-a-simplified-breakdown/

      Here show’s a way to ignore classes like .hidden-xs in the Gruntfile.js:

          uncss: {
                dist: {
                  options: {
                    ignore       : ['.hidden-xs'],
                    stylesheets  : ['wp-content/themes/SBWordpress/style.css'],
                    ignoreSheets : [/fonts.googleapis/],
                    urls         : [], //Overwritten in load_sitemap_and_uncss task
                  },
                  files: {
                    'wp-content/themes/SBWordpress/style.clean.css': ['**/*.php']
                  }
                }
              }
            
          });
      
  13. Thanks David, nice to get a short run through / how to for using uncss, I still need to give it a whirl as I saw it mentioned in another article that I read recently, but its on a very long list of things to look at :(

  14. If anyone uses Ruby On Rails and does extensive Integration Testing, my Headhunter Gem does exactly what you need to find unused CSS automatically (see my website link).

  15. I did the same with python.
    https://github.com/peterbe/mincss
    Also uses PhantomJS.
    You can run it with a list of URLs.

  16. I did not read the whole article but the comments seems more interesting, never thought theres so much on this subject. Good work guys !!

  17. Dan

    This is good but needs to be a web app to be quicker and easier by uploading your CSS file and then viewing the results.

  18. Thomas Semmler

    Does this also work with php files, or does it only support *.html?

    • Supports all types of files — it analytics script *output*.

    • Carlos Rico

      But if I want to integrate this as a task in build time of my project, where my templates have not yet been processed, would it be possible?

  19. For this to work on Foundation 5, had to add this to options:
    ignore: [/meta\..+/]
    Otherwise Syntax error, unrecognized expression: [data-'Times New Roman'-abide] is thrown.

  20. Derek

    This looks cool, but there are so many valid unanswered questions. Sigh…

  21. Ian

    Wish someone could make a GUI app for this that, say, you could integrate with a browser and manually browse a dynamic site like WordPress, ending up with all the used CSS that you could then combine and minify. Maybe then it could go with a plugin that would handle some kind of output of the app, automatically deregister stylesheets and scripts not in use, and use the minified CSS/js to then run the site. I don’t know why this is still a far-off dream for the layperson. Speeding up the web in a simple way would be great for everyone.

  22. Andrew

    David, any ideas on how to use uncss with a site that has a “members” area that you login to via the http post request. I have managed to login and get screenshots of the members area using PhantomJS directly, but can’t see anyway to do this when using uncss. Thanks.

  23. Mark

    I ran this on a larger site and it seems like it removed all the JS injected CSS Classes. For example Bootstraps .collapsing, .collapse.in, btn.disabled etc …

    I’ve had a somewhat easier time with PHPStorm using “Inspect Code” and checking ‘unused css’ and cleaning it up that way. The ease of letting something else do it for me is appealing, but not at the expense of termites.

  24. For those wondering how to use this with WordPress I highly recommend checking this out:

    https://gladdy.uk/blog/2014/04/13/using-uncss-and-grunt-uncss-with-wordpress/

  25. does this functional codes remove all unused css-s from entire a website with a root address?

  26. Awesome!

    Is it possible to output resulting stylesheet to a file instead of:

    uncss(rawHtml, options, function (error, output) {
        console.log(output);
    });
    

    ?

    Thanks

  27. Figured it out!
    This is useful because cmd window in Windows is limited and won’t show all output if the output is too big.

    const fs = require('fs');
    
    uncss(files, options, function (error, output) {
        console.log(output);
    
    
        fs.writeFile("output.txt", output, function(err) {
            if(err) {
                return console.log(err);
            }
    
            console.log("The file was saved!");
        }); 
    });
    

    I’m about to write a complete how to guide to install node.js and use uncss on Windows on my blog http://simonjonsson.com

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!