Using CSS Image Sprites

Even fast connections suffer from multiple HTTP request overhead because of network latency and HTTP request processing overhead.
MSIE7 opens no more than 2 connections per domain, Firefox3 – 4-6 connections, Google Chrome – 6 connections.
Let’s suppose that time to first byte is 70ms (typical response time of http://google.com via 1.5 Mbps ADSL connection from Dulles)
If a page view involves loading of 20 images from the same domain, then total overhead in MSIE7 is 20/2*70ms = 700ms. The more images site contains, the more time visitor will have to wait.

The popular solution is to use CSS Image Sprites:
Join design/logo images into one bigger image. Use spriting technique (css background) to show the images on page. An image can be defined via css property background-position.
This approach is compatible with modern browsers (and even with IE4).

Let’s review the process step by step:
Step1.
Replace image entries <img src="/img/anyimage.gif"> with <div class="i_anyimage"></div>.

Add new css entry:
.i_anyimage
{
width: 17px;
height: 17px;
background-repeat: no-repeat;
background-image: url('/img/anyimage.gif');
}

At the end you should get your pages fully functional and identical to the originals.

Step2.
Now you should join all the images into one bigger file. You can use an image editor or create automated script, etc.

Once the image is ready you start to change the css entries so they use the sprite image instead of original image:
.i_anyimage
{
width: 17px;
height: 17px;
background-repeat: no-repeat;
background-image: url('/img/sprite.png');
background-position: -XXpx -YYpx;
}

XX, YY are coordinates of the original image within the sprite.

What can be useful to know here:

  • Image compression format – which is better? I recommend to use 8-bit PNG format for non-photo images when it’s possible and JPEG format for photo images.
    Some images can be saved in PNG8 without visible loss of quality and it makes sense to do so since this will reduce size of file by about 50% comparing to truecolor PNG. PNG8 also compresses better than GIF and PNG8 supports GIF-like transparency. Size of PNG8 file is 20% less than GIF in average.
  • Make sure your PNG compressed well. There is a number of PNG compression tools, a good example is command-line tool pngcrush.
    You can compress PNG using this command:
    pngcrush -rem alla -brute -reduce src.png dest.png
  • There can be complicated positioning case if your site already using background images that are aligned to the right side or to the bottom of element. In this case you should take horizontal positioning of image chain for aligning to the bottom (and the bottom-aligned image should be on the bottom of the sprite) or vertical positioning in case of aligning to the right side.
    If you have 2 or more images aligned to the bottom right corner, then you will have to make at least 2 sprites (or keep 1 image separated).
  • If you have a margin around your existing background image then you also should leave a margin inside the sprite
  • There are a few tools exists for creating sprites. I like this one: SmartSprites, because it covers most of those complicated cases, supports PNG8 and it’s able to convert Stylesheet files. At the moment the tool is in alpha stage but already looks promising.
  • Images containing Photos and Avatars can be joined into separated sprite in JPEG format. Size of file with a photo in JPEG format will be smaller than file in PNG format. Just don’t try to convert every image you have into sprites. If your page contains 1-2 photos keep them as is. But if the main landing page of the site contains a serie of thumbnails/avatars that changed once per 1 day, then probably they are good candidates to be joined into a JPEG sprite. You should specify appropriate Cache-Control: max-age for this sprite.
    Keep in mind that if there are pictures that change every few minutes then it would unpractical to include them into sprite because then you would have to refresh the sprite very often.
  • CSS Sprite Problems

  • SEO, user agents with disabled images
    If we use DIV or SPAN elements as image container we lose possibility to define ALT attribute. This means that visitors will not see the content (value of ALT attribute) if they are browsing with turned off images. It takes place even if we transform ALT=”" into TITLE=”".
    It also affects search engine spiders, they also don’t see your content.
    In case of images inside links it’s even worse since visitors don’t see the links and search engines skip your anchor keywords.
    Happily, there is an easy solution exists. We should use IMG tag with transparent GIF as image container:
    <img src="/images/transparent.gif" class="i_logo" alt="keywords here" />
  • Complexity of Building Image Sprites
    Applying Image Sprites involves putting effort into building and maintaining Sprites and changing Stylesheet. This can be time consuming especially if you often change images.
    In addition, there are cases when you cannot put all images into sprites. I already mentioned case with several background images aligned to bottom right. Another case is when you have element with size depending on its internal content and you don’t know how big can it be. Then you cannot use a part of sprite as background because there are another images near the part.
  • Complex Sprite Composition
    If there are many images, usually each image appears on the page after loading. We join them into one sprite and browser will wait till the whole sprite loaded. This will increase time to the moment when most visible images appear on the page.
    If we want an image or a group of images to load faster, we can split the sprite into two or more and preload important sprites via Javascript in document’s head.
    Also, if there are several areas with different images we have to decide how many sprites we need and which image should go in which sprite.
    As you see, Sprite Composition can be not so trivial task.
  • View Image
    Visitors cannot view/download separate images inside a sprite. This is another problem if you want some of the images to be shared.
  • 9 comments ↓

    #1 Websites tagged "sprites" on Postsaver on 10.25.08 at 1:17 am

    [...] – Using CSS Image Sprites saved by labmancw2008-10-21 – javascript game development with ext js – part 1 – sprites saved by [...]

    #2 Stylesheet Composition | Web Scaling Blog on 10.31.08 at 7:16 am

    [...] several Stylesheets we join them into one bigger CSS file. As described in the previous post about Image Sprites, we want to reduce amount of downloaded components because of HTTP request overhead. And if in case [...]

    #3 Website Speed Optimization and Waterfall Diagram | Web Scaling Blog on 11.10.08 at 11:34 am

    [...] It reduced Full Load Time from 2.4s to 2s. And we had only 7 images – usually sites contain much more and improvement will be more significant. CSS Sprites were described in one of previous posts. [...]

    #4 michael on 07.17.09 at 5:03 am

    great post, very informative

    #5 House Shutters on 09.04.09 at 12:43 pm

    Great article – I have been researching rollover links for 3 days now. I didn’t discover the CSS only solution until the 3rd day and I found this article while trying to find a way to make it SEO friendly. The transparent image was a great idea, thanks.

    #6 Wonderer on 09.28.09 at 8:02 pm

    If we use the transparent gif we get another HTTP request, then what is the point of using css sprites then?

    The whole meaning of sprites is to lower the number of HTTP requests….

    #7 Nail on 10.20.09 at 1:50 am

    Wonderer,
    If you use transparent gif then you have 2 HTTP requests (1 – image spite, 2 – empty image).
    And if your sprite includes more than 2 images then the number of HTTP requests is lowered.

    #8 cobuncopy on 03.04.10 at 4:56 pm

    video

    game

    funny

    great

    download

    great.

    #9 cobuncopy on 03.04.10 at 7:32 pm

    funny

    downloads

    fun

    videos

    games

    top.

    Leave a Comment