How To: Optimize Your Site with Image Sprites

With my last few posts on website optimization, one of the larger areas of focus was reducing HTTP requests. By reducing the number of requests your browser must make to retrieve all of your website, you speed up your site's loading time with less overall HTTP latency for requests. If you want a good analogy for this method of site optimization, think of hard drive file transfers. Copying 1,000 files in the kB range will take longer than copying a single gigabyte file because starting and stopping 1,000 tiny transfers is more work than just doing a few large ones.

Using image sprites is sort of a last resort after you have done as much as you can with other optimization techniques. A sprite is an image that has all of your other images inside of it, so if your sprite has 10 images, you'd be getting rid of 9 HTTP requests and speeding your site's loading time up by the time for each of those 9 requests' latency. That and there are issues like server overhead for each HTTP request, which has to be served by an Apache child that can take up 20MB of server RAM. You're better off helping your server process less HTTP requests, off-loading media to Amazon S3, et cetera.

Image sprites are used in conjunction with CSS to determine which part of the image sprite will be displayed. Below are two image sprites - one from Google and one from me.

Image Sprites

Creating the Sprite

Following the examples above, round up all of the frequently used images on your website - images like your logo, RSS icon and others that aren't often changed. Place them in a single image in Photoshop or your image editing tool of choice. You can put them as close together as you'd like but it is easier to select them in the next step when they are slightly spaced out. Save the image.

Writing the CSS

With image sprites, you will have CSS selectors for each link that display only a portion of the image sprite - effectively showing just the image you need. You need to find out the exact size and position of the image you wish to display. Do this by using the Slice tool in Photoshop and selecting one of the images you want to use. Right-click on the new slice and select Edit Slice Options. This will bring up a window with the location and dimensions of the image.
Image Sprites

In this case, the image I want to use in my sprite is 42x42 pixels, has a 336px offset and starts from the top of the image. This corresponds to the following CSS:

a.stammy, a.stammy:hover{      background:#fff url(path/to/sprites.png) -336px 0 no-repeat;      display:block;      height:42px;      width:42px;      text-indent:-9999px;      overflow:hidden; }

The CSS selector applies to the links with class="stammy" set. The background attribute loads the sprite and then sets the background position to 336 pixels over - it must be negative. If the image was 10 pixels from the top of the image, the background position would be "-336px -10px". The width and height attributes are then set in the CSS. I also included the hover pseudoclass since I had a problem that when I hovered over links with this class, they would turn the color of my link hover state, making the background image disappear.

Setting overflow hidden "fixes the annoyance of when you select the text you’ve replaced the highlighting stretches all the way to the left side of the screen" as stated by Rob.

Do this for every other image in your sprite, using different names for each selector.

Writing the XHTML

By now you should have quite a few CSS selectors for each image sprite. You've already done the hard parts and you're on the home stretch. All you need to do know is create links with the class for each corresponding CSS selector. Here's what the link for my "stammy" selector (the image is my mug shot) looks like:

<a class="stammy" href="http://link/to/whatever.com" title="Paul Stamatiou">Paul Stamatiou</a>

Simple enough eh? Setting the class combines the image sprite info from the CSS with the link, showing only that region of the sprite. However, since we are not even using an img tag, we can't set an alt attribute, which is vital for mobile visitors, search engines, screen readers and the like. By putting text inside of the link and moving it off the screen with text-indent in CSS, you get the benefit of usability without having the text overlay on top of the image.

In a Nutshell

  • Too many HTTP requests are bad.
  • Using too many images adds to that problem.
  • Image sprites can help.
  • Image sprites are easy to implement and big companies like Google have been using them to save bandwidth for years.