AssetGraph plugin for creating sprites from background images
JavaScript CSS HTML
Latest commit 7a9ffa9 May 11, 2017 @papandreou papandreou Adjust expected output
Failed to load latest commit information.


Gitter NPM version Build Status Coverage Status Dependency Status

A plugin (or "transform") for AssetGraph that optimizes CSS background images by creating sprite images. The spriting is guided by GET parameters and a set of custom CSS properties with a -sprite- prefix.

You can tell AssetGraph-sprite that you want to sprite a given CSS background image by adding a sprite parameter to its query string:

.classone {background-image: url(images/thething.png?sprite=mySpriteGroup); }
.classtwo {background-image: url(images/theotherthing.png?sprite=mySpriteGroup); }

This is valid CSS and will also work fine on its own in "development mode" without a compilation step, so you don't need to rebuild your project all the time, except when you want to test the spriting itself. After being run through the AssetGraph-sprite transform it will look something like this (123 is the id of the generated sprite asset and could be any number):

.classone { background-image: url(123.png); background-position: 0 0; }
.classtwo { background-image: url(123.png); background-position: -34px 0; }

Some additional parameters are supported:


Adds "keepaway space" around the image in the sprite. Sometimes useful if the background image is applied to an element that takes up a bigger area than the background image. Supports regular CSS padding syntax, including the shorthand variants with 1, 2, or 3 values. The only supported unit is px. Defaults to 0 0 0 0. Not supported by the jim-scott packer (see the docs for -sprite-packer below).


Tells AssetGraph-sprite that you want this selector to contain a background-image property pointing at the sprite image, even if the sprite group has a "group selector" configured (see below).

Configuring a sprite

If you can guarantee that the HTML elements that need to have the background image applied are also matched by another selector, you can save some more bytes by telling AssetGraph-sprite that it only needs to add the background-image property pointing at the sprite to that selector using the -sprite-selector-for-group property:

.foo { -sprite-selector-for-group: mySpriteGroup; }
.classone {background-image: url(images/thething.png?sprite=mySpriteGroup); }
.classtwo {background-image: url(images/theotherthing.png?sprite=mySpriteGroup); }

... which compiles to:

.foo { background-image: url(123.png); }
.classone { background-position: 0 0; }
.classtwo { background-position: -34px 0; }

AssetGraph-sprite tries to preserve as much of the original CSS as possible, including existing background or background-image properties in the group selector and the priority (!important status), for example:

.foo { -sprite-selector-for-group: mySpriteGroup; background: red !important; }
.classone { background: blue url(images/thething.png?sprite=mySpriteGroup) !important; }

Compiles to:

.foo { background: red url(123.png) !important; }
.classone { background: blue !important; background-position: 0 0; }

You can tweak the generated sprite images by putting additional -sprite-prefixed configuration properties into the "group selector", for example:

.foo {
    -sprite-selector-for-group: mySpriteGroup;
    -sprite-packer: horizontal;
    -sprite-background-color: #a767ac;

These options are currently supported:

-sprite-packer: horizontal|vertical|jim-scott|try-all

Selects the packing algorithm for the sprite. The horizontal and vertical variants naively lay out the images one after the other. This works well when you have a bunch of images with the same height or width. The jim-scott packer is a little fancier, it's an implementation of a floor planning algorithm originally invented by Jim Scott for packing lightmaps. The Jim Scott packer doesn't support the -sprite-padding property on the individual images. If you don't specify -sprite-packer, the default is try-all, which runs all the algorithms and chooses the packing that produces the smallest sprite image (area-wise).

-sprite-location: url(...)

Specifies the desired location of the sprite. This is useful in combination with the processImages transform if you want to postprocess the generated sprite image:

.foo {
     -sprite-selector-for-group: mySpriteGroup;
     -sprite-location: url(mySprite.png?pngquant=128);
.classone { background-position: 0 0; }

Compiles to:

.foo { background: red url(mySprite.png?pngquant=128) !important; }
.classone { background-position: 0 0; }

-sprite-image-format: png|jpg

The format of the generated sprite. More will be added when node-canvas gains support for more image formats.

-sprite-background-color: red|yellow|#123123|transparent|...

Specifies the background color for the generated sprite image, supports any color syntax understood by node-canvas, which is the entire CSS3 Color Module, as far as I can tell. Defaults to transparent.


For creating the sprite images themselves AssetGraph-sprite uses node-canvas, which is not a pure-node module and requires the Cairo development sources (version 1.10 or later), libjpeg (version 8 or later) and libgif. On Ubuntu 10.10 and above you should be able to get them like this:

$ sudo apt-get install libcairo2-dev libgif-dev libjpeg8-dev

Now you can proceed to install AssetGraph-sprite:

$ npm install assetgraph-sprite


Since AssetGraph-sprite is intended to be used as part of an AssetGraph workflow, first you'll need to have AssetGraph installed to use it properly:

$ npm install assetgraph

Here's a stripped-down example that loads all CSS files in a directory, loads all the images linked to by background and background-image properties, sprites them according to the -sprite-... instructions, then writes the resulting CSS and all the images to a different directory:

var AssetGraph = require('assetgraph');

new AssetGraph({root: "path/to/css/files"})
    .populate({followRelations: {type: 'CssImage'}})
    .writeAssetsToDisc({url: /^file:/}, "file:///my/output/dir")
    .run(function (err) {
        if (err) throw err;
        // All done!

For a more elaborate example of how AssetGraph-sprite can fit in a workflow, see the buildProduction script in AssetGraph-builder


AssetGraph-sprite is licensed under a standard 3-clause BSD license -- see the LICENSE-file for details.