Blog

Printing CSS Sprites

We all know the glory of CSS sprites–they decrease HTTP requests, speed up load time, and make image edits a breeze. However, their one glaring problem is that they're downright impossible to print. Browsers refuse to print backgrounds, and that includes background images. That means your sprited page will look terribly wrong when you try to print, even if you've offered up a pristine print.css file. What to do? Use jQuery to replace your sprited tags with good ol' img elements.

First, you'll want to isolate your code into a function you can use with any CSS selector.


function replaceSprite(selector){
if ($.browser.msie == true) {
        var back_x = $(selector).css('background-position-x'),
            back_y = $(selector).css('background-position-y'),
            back_position = back_x+" "+back_y;
    } else {
        var back_position = $(selector).css('background-position');
    }

    var back_image = $(selector).css('background-image'),
        width = $(selector).width(),
        height = $(selector).height(),
        index1 = back_image.indexOf('http'),
        index2 = back_image.indexOf('.png');

    back_position = back_position.split(" ");
    back_image = back_image.substring(index1, (index2+4));

    $(selector)
            .append('<img src="'+back_image+'"/>')
        .css('width',width)
        .css('height',height)
        .css('overflow','hidden');

    $(selector).find('img')
        .css('margin-left',back_position[0])
        .css('margin-top',back_position[1]);
}

First, we take the attributes of the sprite and store them in variables that we can later tack on to the img element. Note that IE needs separate attribute calls for background-position-x and background-position-y, whereas competent browsers are fine with just background-position.


if ($.browser.msie == true) {
    var backx = $(selector).css('background-position-x'),
        backy = $(selector).css('background-position-y'),
        backposition = backx+" "+backy;
} else {
    var backposition = $(selector).css('background-position');
}

var backimage = $(selector).css('background-image'),
    width = $(selector).width(),
    height = $(selector).height(),
    index1 = backimage.indexOf('http'),
    index2 = back_image.indexOf('.png');

Next, we convert the background-position variables into an array, and we do some substring magic to extract just the image URL from its full background-image CSS syntax.


backposition = backposition.split(" ");
backimage = backimage.substring(index1, (index2+4));

Now it's time to create the img element. (My code assumes that an empty block-level element houses the sprite.) Here we append an img to our selector, change the parent element's properties to fit our new image, and finally give the img the right margins to position it.


$(selector)
    .append('')
    .css('width',width)
    .css('height',height)
    .css('overflow','hidden');

$(selector).find('img')
    .css('margin-left',backposition[0])
    .css('margin-top',backposition[1]);
Now all there is to do is call the function and pipe in a selector, like this.

replaceSprite('div#sprite');
Voila! Your sprites are ready to print. You can combine jQuery CSS assignments into one line of code; I've broken them down here so it's easier to see what's going on. Also, I've told the function to look for .png images, but you can of course change that to whichever file type you like, or better yet, add some auto-detecting code. Happy spriting!