Use Gulp and UnCSS to slim down your CSS framework Jul. 29th, 2015 Chris Ruppel

Use Gulp and UnCSS to slim down your CSS framework

July 29th, 2015

CSS frameworks are a nice way to get started with a project. You can tell by the name of many popular frameworks: Bootstrap, Foundation, and Skeleton just to name a few. All of these names evoke a starting point — problem is, unless you take time to eliminate the pieces you did not use, you’ll ship bloated code to your users.

Start with everything, ship what you need

When getting started on a project, it’s useful to have a wide variety of tools at your disposal. No matter which you choose, it’s pretty certain there will be several main tools: a layout mechanism, utilities to style forms, buttons and other CTAs, sidebars, and so forth. Having these at your fingertips gets development moving and allows you to focus on the specifics of your project.

However, once it’s time to ship, leaving the full framework in place means you’re delivering unnecessary bloat to every user. Maybe you used three of the six buttons they provide, or decided to implement your own grid system mid-project. Removing these by hand is tedious and a bit precarious, since you might accidentally remove something that’s being used.

UnCSS to the rescue

A common way to avoid this issue is to use UnCSS, a tool which will compare your HTML and CSS, removing the bits of CSS that it finds are unused. It uses PhantomJS under the hood to render a set of pages, including JavaScript. Once the page is rendered in memory, it compares all the selectors in the rendered page to the CSS source files. From there it can generate a new CSS file that contains the selectors you actually used and nothing else!

Automating UnCSS

UnCSS is a snap to use. You give it a list of CSS files and a list of URLs that it should render, and it does the rest. The example gulp-uncss task in our frontend performance training kit reduces a copy of Bootstrap significantly. You can see it in the context of a bigger Gulpfile on GitHub but here’s the task itself:

var gulp = require('gulp');
var uncss = require('gulp-uncss');

gulp.task('uncss', function() {
  return gulp.src([
      'node_modules/bootstrap/dist/css/bootstrap.css',
      'node_modules/bootstrap/dist/css/bootstrap-theme.css'
    ])
    .pipe(uncss({
      html: [
        'http://localhost:4000/',
        'http://localhost:4000/audit/',
        'http://localhost:4000/foundation/',
        'http://localhost:4000/budgets/'
      ]
    }))
    .pipe(gulp.dest('css/'));
});

The steps in the task are:

  1. Specify the original Bootstrap assets (we included them using npm so they’re in the node_modules directory.)
  2. Specify some URLs that should be used as HTML reference. You can specify plain HTML files, but in our case the locally-running Jekyll site is used.
  3. Our final destination is css/ at the root of our project. The contents of this directory are ignored by git since everything within is generated by Gulp.

Even if you use the minified copies as a starting point the savings are pretty tremendous:

File Original UnCSS
bootstrap.min.css 115K 12K
bootstrap-theme.min.css 19K 7.3K

So the CSS files went from 134K to about 19K with no heavy lifting on our part! High five!

Note: our sample task intentionally excludes some necessary pages from the UnCSS task. Since it is designed to be used in a hands-on training, the lesson here is that excluding pages which use unique bits of the framework means your UnCSS results will be incomplete. One recommendation to avoid this problem is to use a styleguide page as your URL, or other reference HTML which is known to contain a complete copy of all possible markup on your site.

Always check the results

A commenter pointed out that UnCSS can potentially strip out styles that only appear after user interaction. Some examples are :hover, :focus, and classes that are added to the DOM by JS.

UnCSS is equipped with an ignore option which allows you to specify which selectors should not be removed.

When I re-tested the exact code in our training kit, I saw that all :hover classes remained in the UnCSS-ified files by default, with no extra configuration needed. However if you rely on JavaScript to add or remove classes used by your CSS, keep this option in mind.

Comments

  • tan ahmed

    So I added

    gulp.task(‘default’, function() {
    return gulp.src(‘css/style.css’)
    .pipe(uncss({
    html: [
    ‘index.html’,
    ‘posts/**/*.html’,
    ‘http://127.0.0.1:9000/’
    ]
    }))
    .pipe(gulp.dest(‘css/’));
    });

    to my gulp file which my company uses and it doesnt do anything strangely… any idea!? thanks!