Foundation and Grunt — Why Use Them?
When creating prototypes and/or HTML templates at CreativityKills, we use Zurb’s Foundation and Grunt JS most of the time. If you do not know what Foundation is, it’s a CSS framework that basically makes the job of building websites easier. Grunt JS is basically a javascript task runner. It can make your life very very very easy. Believe me.
With that out of the way, I will not go into tutorials on how to use Zurb Foundation and Grunt JS, I will go straight into how to mix and match Zurb Foundation and Grunt JS.
Foundation and Grunt — Installing Grunt JS
If you don’t already have Grunt JS installed on your machine, now would be a good time to get it installed. You would need to have NPM (Node Package Manager), NodeJS and Bower installed on your machine to take advantage of Grunt. Heres a quick guide on how to install Grunt if you haven’t already.
Foundation and Grunt — Setting Up
Alright now, lets get to the codes. First, you want to fire up your Terminal or Command Line. Most of what we’ll be doing will be on here. You can also fire up your text editor.
Let’s create a new directory. This is going to be the root directory for our project. For the purpose of our tutorial, I’ll name this project Acme.
$ mkdir Acme $ cd Acme
Now lets create our package.json, bower.json, and Gruntfile.js. These files will help us add dependencies and configure our whole project.
$ touch Gruntfile.js $ npm init $ bower init
You may have noticed that when you run the commands npm init and bower init, the terminal presented you with options and you had to add values. The commands help you generate the package.json file and the bower.json files.
Now that we have both files, let’s get dirty. First, we want to use bower to install the latest Foundation automatically. So, open your bower.json file and update the file with this:
"dependencies": { "foundation": "zurb/bower-foundation" }
Remember, though, that this file must be a valid JSON file or else you’ll get errors. After saving the file, go to your Terminal and run the following commands:
$ npm install && bower install
This would install packages automatically into your project directory. It’s worth noting that, every time you change the bower.json file or the package.json file, you should run the command above so the new packages will be installed and/or updated.
By now you should notice a new folder created in your projects root directory named “bower_components”. This is where all the Bower dependencies reside. So, we have successfully pulled in our Foundation files into this directory.
Moving on.
Open your Gruntfile.js and lets start configuring everything to work smoothly. You should have a blank file here. Just copy and paste the code below inside it.
module.exports = function(grunt) { // ----------------------------------------- // Start Grunt configuration // ----------------------------------------- grunt.initConfig({ // Load package.json file pkg: grunt.file.readJSON('package.json'), }); }
Now, I would not explain what is going on, because this is not a Grunt tutorial. You can learn about Grunt, if you want, on their website.
At this point, ask, what good is a task runner without any tasks to run? Yeah, so, let us start adding tasks for our Grunt task runner. Let us start by adding basic sass compiler to the task runner, so that Grunt can compile sass file in our project directory.
In your package.json file, let us add a grunt package and have NPM pull it in for us. In the file, add the following lines:
"devDependencies": { "grunt": "~0.4.1", "grunt-contrib-sass": "~0.8.1" }
This will add Grunt support to our project and also add support for sass. This is exactly what we want. Now, as usual, you will have to run the command “npm install” so that NPM can pull in the new changes.
At this point, you should see yet another new directory “node_modules” in the root of the project directory. This is expected.
Now that we have added a task, let us load the task to Grunt, and register it so Grunt can use it.
Loading and Registering Grunt Tasks
To load the Grunt task we just added to the package.json file, let us open the Gruntfile.js file and add in the commands to load and register the new packages/tasks. Add the following lines before the closing bracket in the Gruntfile.js:
// ----------------------------------------- // Load Grunt tasks // ----------------------------------------- grunt.loadNpmTasks('grunt-contrib-sass'); // ----------------------------------------- // Register Grunt tasks // ----------------------------------------- grunt.registerTask('buildCss', ['sass']); grunt.registerTask('default', ['buildCss']);
This lets us load the tasks, and register the loaded task. So now, we have to add a configuration to the Gruntfile.js so that the new task doesn’t act weird. In the Gruntfile.js, we want to add a sass configuration, after the line:
// Load package.json file pkg: grunt.file.readJSON('package.json'),
Add the block of code:
// -------------------------------------- // Sass Configuration // -------------------------------------- sass: { options: { loadPath: ['bower_components/foundation/scss'] }, dist: { options: { sourcemap: 'none', style: 'nested' }, files: [{ expand: true, cwd: 'develop/scss', src: ['*.scss'], dest: 'dist/assets/css', ext: '.css' }] } }
You can find more configuration options for the sass task on the Github repository of the package.
Now let us create some new directories in our projects root directory. These directories are where we’ll put our uncompiled scss files, our uncompiled JS files, and all our compiled files, respectively. Run this command to recursively create the needed directories:
$ mkdir -p develop/scss develop/js dist
Now, let us see if our first Grunt task works normally. Create a new file in the “develop/scss” directory called “style.scss”. We will use this to import foundation and see if all is well with the world.
In the “style.scss” file you just created, add this line of code:
@import "foundation";
Then when you are done, you can run the command “grunt” on your terminal. You should see a bunch of reports and then something saying “Done without errors”. At this point, you should have a new file: “dist/assets/css.style.css”. This is your compiled foundation css file.
I assume at this point, you already know how to use Foundation with sass and you can do the rest all by yourself.
Now this is the “makes life easy” part. We want the Grunt to automatically watch for file changes in our “develop/scss” directory and if there are any, we want Grunt to compile, automatically so we don’t have to start running “grunt” command all the time.
To do this, we have to install a new npm task. To install a new task, we would try a new method, run this command in your terminal:
$ npm install grunt-contrib-watch --save-dev
This will automatically install the package, and overwrite the package.json file to include this new dependency.
Now as usual, we have to load and register the task we just installed using NPM, so add this to the loading task section of your Gruntfile.js
grunt.loadNpmTasks('grunt-contrib-watch');
And then also we have to register the loaded task, so that Grunt adds it when running tasks. To do this, we add this to the “default” register task part of your Gruntfile.js. Edit your Gruntfile.js, and replace the “default” register task with this:
grunt.registerTask('default', ['buildCss', 'watch']);
Now we have to configure the new task we added so lets add, the block of code to our Gruntfile.js file. Replace:
// Load package.json file pkg: grunt.file.readJSON('package.json'),
With this new block of code:
// Load package.json file pkg: grunt.file.readJSON('package.json'), // -------------------------------------- // Watch Configuration // -------------------------------------- watch: { grunt: { files: ["Gruntfile.js"], tasks: ["default"] }, sass: { files: "develop/scss/**/*.scss", tasks: ["buildCss"] } },
You can find more configuration options for the watch task on the Github repository of the package.
The above code just tells Grunt to watch for file changes, and when there is a file change, it runs certain tasks, depending on which file has been changed.
So now, when you run the “grunt” command on your terminal, it stays active. You do not have to run the command again anytime you change the sass files, the changes will be noted and automatically pulled in.
Foundation and Grunt JS — Going further
You can also use Grunt to automatically compile Foundation’s javascript, add LiveReload support (so you do not ever have to click the browser refresh button again) very useful for prototyping.
There is just so much you can do with Grunt, its ridiculous. Let’s see how we can add JS compilation for our project using Grunt.
We are going to use two packages for this, one to concatenate and the other to compress. Let’s start by installing the packages necessary. In the terminal, run these commands (if Grunt is still running you can open a new tab or press CTRL+C to terminate the “grunt watch” process):
$ npm install grunt-contrib-concat grunt-contrib-uglify --save-dev
Now, we can load and register our new tasks in our Gruntfile.js. In that file, add the following to the load and register sections respectively.
grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-concat');
Then we register the tasks also in the Gruntfile.js so our register section looks like this:
// ----------------------------------------- // Register Grunt tasks // ----------------------------------------- grunt.registerTask('buildCss', ['sass']); grunt.registerTask('buildJs', ['concat', 'uglify']); grunt.registerTask('default', ['buildCss', 'buildJs', 'watch']);
Now we have to configure the tasks so that Grunt knows what to do and how to do it when it comes to that task. Let’s configure our uglify and concat tasks.
// -------------------------------------- // Concatenate Configuration // -------------------------------------- concat: { options: { separator: ';' }, script: { src: [ 'bower_components/foundation/js/foundation/foundation.js', 'bower_components/foundation/js/foundation/foundation.alert.js', 'bower_components/foundation/js/foundation/foundation.abide.js', 'bower_components/foundation/js/foundation/foundation.joyride.js', // ...more foundation JS you might want to add 'develop/js/script.js' ], dest: 'dist/assets/js/script.js' }, modernizr: { src: [ 'bower_components/modernizr/modernizr.js', 'develop/js/custom.modernizr.js' ], dest: 'dist/assets/js/modernizr.js' } }, // -------------------------------------- // Uglify Configuration // -------------------------------------- uglify: { dist: { files: { 'dist/assets/js/jquery.min.js': ['bower_components/jquery/dist/jquery.js'], 'dist/assets/js/modernizr.min.js': ['dist/assets/js/modernizr.js'], 'dist/assets/js/script.min.js': ['dist/assets/js/script.js'] } } },
Now we want to create two files in our “develop/js” directory. These files will be where we will store our own JS and our custom modernizr js.
$ touch develop/js/script.js develop/js/custom.modernizr.js
In the “develop/js/script.js” file, we can start off by doing this:
(function($){ $(document).on('ready', function(){ $(document).foundation(); }); })(jQuery);
Now, we can run our “grunt” command in the terminal once more and we should see a bit more messages. However, right now, if we change our script.js file, it doesn’t get automatically compiled and concatenated. So let us add a watch configuration for JS files so anytime there is a change in the JS directory, we run our “buildJS” task.
In our Gruntfile.js, edit the “watch” configuration so it looks like this:
// -------------------------------------- // Watch Configuration // -------------------------------------- watch: { grunt: { files: ['Gruntfile.js'], tasks: ['default'] }, sass: { files: 'develop/scss/**/*.scss', tasks: ['buildCss'] }, script: { files: 'develop/js/**/*.js', tasks: ['buildJs'] } },
Now we have added a new “script” configuration to the “watch” task. This change should be immediately visible from the Grunt task reports in the Terminal.
You can go on and create your HTML files in the “dist” directory or anywhere you want for that matter. Just make sure to link to your asset files in the “dist/asset” directory. Here’s an example of an “index.html” file in the “diet” folder:
Foundation Grunt | Welcome Welcome to Foundation
That’s all for now, but, like I said earlier, you can add livereload functionality to your Gruntfile so that file changes will automatically trigger a browser refresh.
You can download the whole Foundation and Grunt code as a zip on the Github repository, or clone it, which ever way you want to swing it. Note, though, that several tasks not mentioned in this article have been added to the Github repo version.
Hope this helps someone out there set up Zurb Foundation and Grunt JS flawlessly.