How To: Optimize Your Site with Image Sprites

July 25, 2007 · 41 comments

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 42×42 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.

{ 14 trackbacks }

Sam Lu - goSammy » Link Sharing: On Optimizing Your Website
July 25, 2007 at 8:24 am
links for 2007-07-25 | nicharalambous.com
July 25, 2007 at 10:20 am
All in a days work…
July 26, 2007 at 12:06 am
Links for 7/26/07 [my NetNewsWire tabs]
July 26, 2007 at 9:01 am
Sebastian Bauer (IT-Blog)
July 30, 2007 at 3:29 pm
Optimizing Wordpress for Best Performance
August 13, 2007 at 10:02 am
Is Minimizing the Number HTTP Requests Worthwhile? | The Light Bulb Cluster
August 24, 2007 at 7:22 pm
Advanced Guide On How To Choose A Good Web Host
September 23, 2007 at 12:33 pm
Sebastian Bauer (IT-Blog) » Blog Archiv » Webentwicklung: Performance Optimierung durch Image Sprites
November 9, 2007 at 4:25 pm
Faster Loading Pages with CSS Background Image Sprites :: Synapse Studios Blog
June 2, 2008 at 1:28 pm
Wordpress Theme Modification : Designers community
January 2, 2009 at 2:06 am
phpgamespace.com
March 3, 2009 at 7:11 am
How To: Optimize Your Apache Site with Mod Deflate - PaulStamatiou.com
April 23, 2009 at 5:17 pm
Site Redesign: Everything’s Bigger In Texas Edition — PaulStamatiou.com
May 4, 2009 at 1:08 am

{ 27 comments… read them below or add one }

1 Chris Marshall July 25, 2007 at 4:32 am

More food for thought – thanks. I think I need to look at all this for my own site sooner rather than later, which is somewhat daunting!

Reply   More from author

2 Brian Heys July 25, 2007 at 7:17 am

Good idea Paul – and another well-written guide. :)

I’m in the process of planning a redesign for both my sites at the moment, so I’ll probably end up using this.

Reply   More from author

3 Sam Lu July 25, 2007 at 7:42 am

Really digging these optimization posts, never would’ve thought of this stuff.

Reply   More from author

4 Andrew Swihart July 25, 2007 at 7:54 am

This is a very interesting guide, nice job.

Reply   More from author

5 Ash Haque July 25, 2007 at 8:51 am

I usually end up doing this for background icons and such but then you end up having to use a really wide or long image to make sure it doesn’t repeat again.

Reply   More from author

6 Adam Teece July 25, 2007 at 9:03 am

This is really awesome. I never really thought of it. I might integrate it into the WP theme I am slowly working on.

Reply   More from author

7 Josh P July 25, 2007 at 9:53 am

For what it’s worth Paul, you don’t need that div tag inside the link. You can put the text-indent in the link CSS.

Reply   More from author

8 Abi July 25, 2007 at 10:11 am

Thanks for writing about this in such an easy to understand way.

Reply   More from author

9 Dr J July 25, 2007 at 10:45 am

nice writeup. this definitely is a great way to save some bandwidth and is quick and easy to implement

Reply   More from author

10 Dumitru Tira July 25, 2007 at 1:36 pm

This is really useful on huge sites or blogs with a lot of daily visits, this small changes will show up some great results :)

Then creating a blog template with a lot of icons and stuff like that this is awesome, saves lots of requests.

Good Post

Reply   More from author

11 Paul Stamatiou July 25, 2007 at 2:39 pm

@Josh P – thanks!

Reply   More from author

12 Phil Freo July 25, 2007 at 5:46 pm

Paul, glad you got this working correctly… fun times last weekend, glad you could come out.

Reply   More from author

13 arammos July 25, 2007 at 6:21 pm

Thnx very useful.

Reply   More from author

14 Mark Jaquith July 25, 2007 at 6:55 pm

This is a MUST for creating image rollover effects, as it completely eliminates the delay. See the tabs at my personal blog for an example.

What would be amazing is a tool that slurps up a bunch of images, combines them, and gives you the CSS to pick out the individual images. The only problem with CSS sprites is that it’s a lot of work.

Reply   More from author

15 Andrew Swihart July 25, 2007 at 8:00 pm

Paul, I was just thinking, all your website performance stuff is great, but is there any tangible benefit to doing any of it? I’d be interested if you know of any scientific studies that show that doing optimizations like compressing css and using image sprites lead to more traffic because visitors liked the responsiveness. Or do you do all this stuff more to conserve bandwidth?

Reply   More from author

16 Paul Stamatiou July 25, 2007 at 8:06 pm

@Andrew – I do this because I love speed! There is a study, however, stating that if your site doesn’t load within 4 seconds, people will leave.

More importantly, with these optimizations, I am prepared for high-levels of traffic and can handle many thousand hits the next time I get dugg or what have you.

Reply   More from author

17 Rob Goodlatte July 25, 2007 at 9:05 pm

Paul,

If you use the text-indent: -9999px trick you should also add overflow: hidden

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.

Agreed w/ Josh — The div isn’t needed, especially w/ inline style.

Reply   More from author

18 Chris July 26, 2007 at 3:20 am

@Rob: don’t use “overflow:hidden;” for this removing the link border that appears onclick … there’s actually a CSS property for the expressed purpose of control this border: outline. Simply do “outline:0;” and no nasty border that stretches off screen. The problem with “overflow:hidden;” is that while it may work, it adds extra styling (namely hiding overflow) which is unnecessary and possibly even problematic depending on what you’re trying to accomplish.

Reply   More from author

19 Chris July 26, 2007 at 3:23 am

@Rob: okay, so I apparently can’t read. You were talking about something different, but heck, outline:0; is a good thing to add into the mix if you’re using negative text-indent on a link, regardless.

Reply   More from author

20 Mike Papageorge July 26, 2007 at 5:34 am

Nice write-up, Paul.

I wrote about this topic a while back and have some explanation on packet sizes, http requests and optimizing if yer interested:

http://www.fiftyfoureleven.com/weblog/web-development/css/css-sprites-images-optimization

Reply   More from author

21 JD July 26, 2007 at 7:38 am

The interesting thing is that, in the past, people would advocate splitting images into several pieces so that they would load in parallel (faster)… ^_^

Reply

22 Blake Brannon July 26, 2007 at 12:24 pm

Paul,

Any idea if there are browsers that do not support CSS code for sprite images or mobile browser that will render the image incorrectly?

Reply   More from author

23 Jeremy David July 27, 2007 at 2:20 am

Hey Paul,

‘just had a quick question about your webhosting… thought it was sort of relevant to this post.

I’m having a terrible time deciding where to host the blog I’m making for my around-the-world-trip. I’m obsessed with having a fast loading page, but at the same time I’m not expecting a considerable amount of traffic. Unless for some reason people start to care about my trip, ha ha.

Is shelling out the extra $10 / month for hosting like media temple worth it?

Cheers dude,

Jeremy

Reply   More from author

24 Paul Stamatiou July 27, 2007 at 2:24 am

@Jeremy – honestly, it’s up to you. I’ve pretty much only used (mt) and have had a good experience with great service. You could always pickup a really cheap/crappy webhost and host images on Amazon S3 so they’d be fast and all, but that seems like another step between you and your readers.

Reply   More from author

25 Jeremy David July 27, 2007 at 1:14 pm

Thanks Paul!

Reply   More from author

26 Jonathan Solichin July 27, 2007 at 9:46 pm

Thanks Paul, I’ll be sure to do this in my next re-design! Thanks again!

Reply   More from author

27 Joey Primiani August 19, 2007 at 2:45 pm

I have been experimenting with Sprites for a while, haven’t implemented them yet. I really want to start using Amazon S3 like you said to save on speed. Great article!

Reply   More from author

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Previous post: flickrSLiDR Has a New Owner

Next post: Review: Yahoo! YSlow for Firebug