Foundation 5, Sass and Grunt Uncss

This post is over six (6) months old. Some things on this page my be out of date or no longer applicable.


CSS Frameworks are bloated! At least that is the argument. They can be is the truth. A standard Sass install with all components included of Foundation 5 is 111KB uncompressed 16 Kb compressed. They can also be as slim as you want. You can use only the parts you want when you use tools like Sass (scss) but that still may leave over unwanted styles. Grunt Uncss can fill in those gaps and shrink our file down even more.

The following tutorial will use these grunt plugins and these Foundation templates
Grunt Plugins Foundation Templates
Foundation 5 Sass Banded
Grunt Uncss Feed
Grunt Cssmin Grid
Grunt Processhtml Marketing
Grunt Autoprefixer Store

Seeing that list of Grunt plugins, and their github pages might put a lot of people off. It looks hard. The great thing about grunt is: If you don't want to use a plugin dont. If it doesn't fit your workflow, don't use it. Its about your workflow and what works best for you.

Setup

We'll start off by creating a new Foundation 5 project. Mine will be in my htdocs directory of my xampp install. This project will be named uncss and will use libsass. Starting this project will give you a leg up by giving you a package.json and a gruntfile.js.


C:\xampp\htdocs>foundation new uncss --libsass

After you have completed the Foundation install you can then move on to setting up your gruntfile. Change directoies in your terminal/command prompt to your newly created project. You will install all of the above mentioned grunt plugins at once. Leave out any plugins you don't want to use. You may also elect to install the plugins one at a time.


npm install grunt-uncss grunt-contrib-cssmin grunt-processhtml grunt-autoprefixer --save-dev

This will download the plugins, save them locally to your project and update your package.json file. You can then move on to loading the tasks, enabling the tasks and actually creating the tasks you wish to run.

Enabling

At the bottom of your Gruntfile you will see the grunt.loadNpmTasks('task here'); you will place your newly downloaded and installed tasks below the ones Foundation has installed for you.


// foundations tasks
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
// ones you wish to use
grunt.loadNpmTasks('grunt-uncss');
grunt.loadNpmTasks('grunt-processhtml');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-autoprefixer');

Uncss Task

Uncss will scan our HTML files for used selectors, remove the unused selectors and create a new, smaller css file. The files you want scanned will be on the right. The newly created css file is on the left. At this point the file and directory of this file don't exist. Once the uncss task has been ran it will create the file and/or directory specified on the left.

Underneath the "Watch" task in your gruntfile place the following


watch: {
  grunt: { files: ['Gruntfile.js'] },

  sass: {
    files: 'scss/**/*.scss',
    tasks: ['sass']
  }
}, // <- notice the comma

uncss: {
  dist: {
    files: { // files scanned on the right. cleaned css on the left in a "cleaned" directory
      'cleaned/css/app-cleaned.css': ['banded.html', 'feed.html', 'grid.html', 'marketing.html', 'store.html']
    }
  }
}, // <- notice the comma

To separate the cleaned css from the full css file I'll save the uncss task created css file into the "cleaned" directory.

Processhtml Task

This task is done in two parts. The first part is creating the task in our gruntfile. Proceeshtml will take the files on the right (our input) and scan those for a snippet we will place in each file then place those in the directory specified on the left.


processhtml: {
  dist: {
    files: {
      'cleaned/banded.html'   : ['banded.html'],
      'cleaned/feed.html'     : ['feed.html'],
      'cleaned/grid.html'     : ['grid.html'],
      'cleaned/marketing.html': ['marketing.html'],
      'cleaned/store.html'    : ['store.html']
    }
  }
},

Here is the snippet we will place in each of the HTMl files on the right of the task


<!-- build:css css/app-cleaned.min.css -->
<link rel="stylesheet" href="css/app.css" />
<!-- /build -->

During the Processhtml task it will search your HTML files for this snippet. It will repleace our "app.css" with the css file with the .min.css extension located in the "cleaned/css" directory. The minified css will come from the cssmin task.

Autoprefixer Task

Autoprefixer will place needed vendor prefixes our css using data from Caniuse . We'll use the default values from the Autoprefixer github page and use the needed prefixes for the last 2 versions of all browser, Internet Explorer 8 and 9 and Android 2.3. The input is our cleaned CSS file from uncss task. We will save it in the same directory under the same name.


autoprefixer: {
  options: {
    browsers: ['last 2 versions', 'ie 8', 'ie 9', 'Android 2.3']
  },
  target: {
    src: 'cleaned/css/app-cleaned.css',
    dest: 'cleaned/css/app-cleaned.css'
  }
},

Cssmin Task

Cssmin will take our file we have created from uncss and autoprefixer and minify it. Again the input file is on the right and our new file with the .min.css extension we will like to create is on the left.


cssmin: {
  minify: {
    files: {
      'cleaned/css/app-cleaned.min.css': ['cleaned/css/app-cleaned.css']
    }
  }
}

Running a Task

You can now open up your terminal/command prompt in your project directory if you closed it and enter grunt [task-name] for each task you wish to run. That is time consuming if you have a large gruntfile and many plugins and kind of defeates the purpose of a task runner. To fix this we will register a task, call this task "clean". This task will build our css from scss the run uncss followed by autoprefixer, minify our prefixed-cleaned css then copy those files over to our "cleaned" directory.

At the bottom of your Gruntilfe in the grunt.registerTask('task name') section place this:


// default foundation grunt tasks
grunt.registerTask('build', ['sass']);
grunt.registerTask('default', ['build','watch']);
// our task we are registering
grunt.registerTask('clean', ['build', 'uncss', 'autoprefixer', 'cssmin', 'processhtml']);

Now we can run grunt clean from your terminal

grunt task running

Results

Before Photo After Photo
Css Size 16KB 4KB

The results are great! We shrunk the complete css file from 16 KB compressed to 4. Your users on low bandwidth connections will love you. After all #PerfMatters .

The only issue we have now is some of the Foundation components no longer work. Things like the topbar will no longer open on small mobile menu screens. Example

Fixing Components

Fixing the broke components can be done at least two ways. The first way is to add an option parameter to uncss and have it ignore the selectors you place there or a regular expression.


uncss: {
  dist: {
    files: { // files scanned on the right. cleaned css on the left in a "cleaned" directory
      'cleaned/css/app-cleaned.css': ['banded.html', 'feed.html', 'grid.html', 'marketing.html', 'store.html']
    }
  },
   options: {
    ignore: ['.top-bar .expanded', 'other selectors']
  }
},

Doing this can fix the problem if you know all of the selectors generated by Javascript or are really handy with regex's.

The other longer more involved method would be to edit your 'app.scss' file in your scss folder. Comment out the main Foundation import in your app.scss file and then proceed to un comment all the components you wish to use. When you come across a component that was broke after running uncss leave it commented out. In this case its topbar.scss


@import "settings";
// @import "foundation";
// Or selectively include components
@import
"foundation/components/accordion",
"foundation/components/alert-boxes",
"foundation/components/block-grid",
/* rest of the components .... */
// "foundation/components/top-bar",

In your scss directory create a new scss file. This file will contain the scss/css files that were broken on the previous running of uncss. Copy over the imports from app.scss into this file and save.


@import "foundation/components/top-bar";

Fixing the Gruntfile

Open up your gruntfile and head to the sass task. We want it to compile a separate style sheet for our topbar scss file. Add this option.


sass: {
  options: {
    includePaths: ['bower_components/foundation/scss']
  },
  dist: {
    options: {
      outputStyle: 'compressed'
    },
    files: {
      'css/app.css': 'scss/app.scss',
      // our component file on the right
      // file to save on the left
      'css/top-bar.css' : 'scss/topbar.scss'
    }
   }
},

Once you have completed that part you'll have to edit the cssmin task. We want to combine the two css files generated by the sass build task into one file after uncss has ran then minify it.


cssmin: {
// the combine task
  combine: {
    files: {
      'cleaned/css/app-cleaned.css': ['cleaned/css/app-cleaned.css', 'css/top-bar.css']
    }
  },
  minify: {
    files: {
      'cleaned/css/app-cleaned.min.css': ['cleaned/css/app-cleaned.css']
    }
  }
}

We can now run grunt clean from our project directory and have a working topbar. Example .

Result Comparison

All components Photo Separate components Photo
Css Size 4KB 5KB

Creating a standalone top-bar.css file will also include all of the grid css classes. You can see from the above example its not much of a size difference when using compression to serve your site (which is highly recommended). You can shrink the entire css file more once you are ready to put your site into production. After you have built your assets (by running grunt build ) you'll have two css files. This instance we'll have app.css and top-bar.css. We can then take steps to shrink this file by running individual grunt tasks. In order to use this option we must remove the unnecessary css from our component css (top-bar.css). Open this file and remove the grid classes and the meta.mq classes and save the top-bar.css. You can then run the individual tasks or build a new task.

Individual

  • Run Grunt uncss (will remove css from our app.css save it as app-cleaned)
  • Run Grunt processhtml
  • Run Grunt autoprefixer
  • Run Grunt cssmin
Before Photo After Photo
Css Size 5 KB (30 KB uncompressed) 4 KB (18 KB uncompressed)
Page Weight 71 KB (246 KB uncompressed) 70 KB (234 KB uncompressed)

Run the clean task at the end of your build process and separate your cleaned css file from your development files in case anything breaks. You don't need to use another directory as I did with 'cleaned'. You could just give it a different name (ie tidy.css or cleaned.css). If something does break you don't have to worry about you writing over the one that worked and you can troubleshoot from there.

Css frameworks don't have to be "bloated" or heavy. With the increase of people accessing the internet with mobile devices it helps to send assets down to their device that aren't littered with unnecessary css.