Automating sprite creation with Grunt

Visita este link para la versión en español.

Why should I use sprites in my project?

Sprites can benefit page speed in several ways. First, if many small images are combined into one large image, the browser will require fewer server connections. Second, depending on how well the large PNG compresses, this can end up saving a substantial amount of bandwidth. Finally, in some browsers it is faster to decode one large image than several small ones.

This is one of Pinterest’s sprites.

Let’s imagine for a moment that we need to add a new image in the existing sprite and rearrange the others around it, we would have to recalculate positions for every class in the stylesheet…

Would you like to do that task manually? I’m quite sure I wouldn’t.

Well, worry no more. Today we’re going to learn how to automate this process with a little help from Grunt, if you don’t know what Grunt is you can read this interesting post by Chris Coyier to get started.

The Grunt task we’ll be using is grunt-spritesmith, for the full documentation visit the Github repo https://github.com/Ensighten/grunt-spritesmith

Now let’s set up the file structure to start creating the sprite of our project: Inside the folder mi-proyecto we have css (where the stylesheet will be created) and the folder img which also contains the sprites folders where we’ll place all the separated images that we’ll join later on. (In order to keep this a basic tutorial we’ll only be working with .png images)

The content of the file package.json is the following:

{
	"name": "mi-proyecto",
	"version": "0.1.0",
	"devDependencies": {
		"grunt": "~0.4.5",
		"grunt-spritesmith": "^2.1.0"
	}
}

and the content of Gruntfile.js is:

module.exports = function(grunt) {
	grunt.initConfig({
	sprite:{
		all: {
			src: ‘img/sprites/*.png’,
			destImg: ‘img/spritesheet.png’,
			destCSS: ‘css/sprites.css’,
			algorithm: ‘binary-tree’
		}
	}
});

// Load task
grunt.loadNpmTasks(‘grunt-spritesmith’);
};

Then we go to the root of our project in terminal and type this line:

npm install

It should look like this so far:

The styles and classes are ready to use in the file sprite.css

/*  
Icon classes can be used entirely standalone. They are named after their original file names.
*/

.icon-ico_alert {
	background-image: url(../img/spritesheet.png);
	background-position: -93px 0px;
	width: 21px;
	height: 18px;
}
.icon-ico_check {
	background-image: url(../img/spritesheet.png);
	background-position: 0px 0px;
	width: 65px;
	height: 60px;
}
.icon-ico_fb {
	background-image: url(../img/spritesheet.png);
	background-position: -65px 0px;
	width: 28px;
	height: 28px;
}
.icon-ico_google {
	background-image: url(../img/spritesheet.png);
	background-position: -65px -28px;
	width: 28px;
	height: 28px;
}
.icon-ico_mail {
	background-image: url(../img/spritesheet.png);
	background-position: 0px -60px;
	width: 28px;
	height: 28px;
}
.icon-ico_time {
	background-image: url(../img/spritesheet.png);
	background-position: -28px -60px;
	width: 28px;
	height: 28px;
}
.icon-ico_twitter {
	background-image: url(../img/spritesheet.png);
	background-position: -56px -60px;
	width: 28px;
	height: 28px;
}

Do you use preprocessors?

We have the option to generate our styles in several formats (CSS, SASS, SCSS, LESS, Stylus).

To create the stylesheet in Stylus, we have to change line 7 of the `Gruntfile.js file and replace it with:

destCSS: ‘css/sprites.styl’,

And we run the grunt sprite task again:

This will create a set of mixins in the `sprites.styl file with all the variables needed, for example;

.icoFacebook
	sprite($ico_fb) // the image name is the same as the variable name
	display: inline-block

Which compiles in css to:

.icoFacebook {
	background-image: url("../img/spritesheet.png");
	background-position: -65px 0px;
	width: 28px;
	height: 28px;
	display: inline-block;
}

We should note that the names of the variables generated in the file sprites.styl are the same names as the .png files found in the img/sprite path.