Click here to Skip to main content
Licence CPOL
First Posted 7 Apr 2009
Views 20,545
Bookmarked 31 times

Optimize your Pages using CSS Sprites

By emiaj | 2 Jul 2009 | Technical Blog
Lets say that you boss calls you telling that the shiny new page of the company in the production server is having a very bad user experience, the load process takes a lot of time and the users have to wait to start using it. You, as a good developer/designer found after a trace of the web requests

1

2
2 votes, 16.7%
3
2 votes, 16.7%
4
8 votes, 66.7%
5
4.71/5 - 12 votes
2 removed
μ 4.60, σa 1.44 [?]

Lets say that you boss calls you telling that the shiny new page of the company in the production server is having a very bad user experience, the load process takes a lot of time and the users have to wait to start using it.

You, as a good developer/designer found after a trace of the web requests/responses that the main issue is related to the downloading process of the images that are being used for several elements in the main page screen...lets say 100 images (pretty large, isn't?).

You check the size of those images and none of them is too large (1kb - 10kb max), then your boss look at you and you simply don't have an answer for such thing... what to do then? start blaming to the user's computers ("is their fault, they should upgrade to a better Internet connection, no less than T1"), or start blaming to the framework? ("is PHP/.net/java fault, I told you so, the decision to go with PHP/.net/java was a really bad idea"), or something else that saves your soul from hell :) .

Here is when a technique named CSS Sprites comes to the rescue. This is an idea ported from the gaming industry and it can be applied to the web too. The main idea is to take all your images (in these case the 100 images) and put them all in a big image, and finally, using CSS move the coordinates around this newly image to show the correct image for a given element.

Lets create an small demo showing this technique: 

The final result should look like this: 
final_result.png

This is our basic markup:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <style type="text/css">
        .container div
        {
            border<span class="code-none">: 1px solid<span class="code-none">;
            float<span class="code-none">: left<span class="code-none">;
            height<span class="code-none">: 100px<span class="code-none">;
            left<span class="code-none">: 20px<span class="code-none">;
            margin-left<span class="code-none">: 12px<span class="code-none">;
            margin-top<span class="code-none">: 50px<span class="code-none">;
            position<span class="code-none">: relative<span class="code-none">;
            width<span class="code-none">: 100px<span class="code-none">;
        <span class="code-none">}
        .blue
        <span class="code-none">{
        <span class="code-none">}
        .red
        <span class="code-none">{
        <span class="code-none">}
        .yellow
        <span class="code-none">{
        <span class="code-none">}
    </style>
</head>
<body>
    <div class="container">
        <div class="blue">
        </</span>div>
        <div class="red">
        </</span>div>
        <div class="yellow">
        </</span>div>
    </

And these are our images:

  

blue.jpg yellow.jpg red.jpg
blue.jpg yellow.jpg red.jpg

Now, the traditional way to do this is just to set the background-image for each selector to target the correct image, something like:

      .blue
        {
        background-image<span class="code-none">:url('blue.jpg')<span class="code-none">;
        <span class="code-none">}
        .red
        <span class="code-none">{
        background-image<span class="code-none">:url('red.jpg')<span class="code-none">;
        <span class="code-none">}
        .yellow
        <span class="code-none">{
        background-image<span class="code-none">:url('yellow.jpg')<span class="code-none">;
        <span class="code-none">}</span></span></span></span></span></span></

And effectively, it does work. But the problem is that you are hitting 3 times the server to retrieve those images. You can get the same result using CSS Sprites, first using your favorite image editing software (Photoshop) we are going to merge those images, the end result should be something like these:

sprite.jpg
sprite.jpg

And here the magic happens, lets change our selectors to use this big image and move the coordinates for each square until we get the desired result:

        .container div
        {
            border<span class="code-none">: 1px solid<span class="code-none">;
            float<span class="code-none">: left<span class="code-none">;
            height<span class="code-none">: 100px<span class="code-none">;
            left<span class="code-none">: 20px<span class="code-none">;
            margin-left<span class="code-none">: 12px<span class="code-none">;
            margin-top<span class="code-none">: 50px<span class="code-none">;
            position<span class="code-none">: relative<span class="code-none">;
            width<span class="code-none">: 100px<span class="code-none">;
            background-image<span class="code-none">: url('sprite.jpg')<span class="code-none">;
        <span class="code-none">}
        .blue
        <span class="code-none">{
            background-position<span class="code-none">: -100px 0px<span class="code-none">;
        <span class="code-none">}
        .red
        <span class="code-none">{
            background-position<span class="code-none">: -200px 0px<span class="code-none">;
        <span class="code-none">}
        .yellow
        <span class="code-none">{
            background-position<span class="code-none">: -0px 0px<span class="code-none">;
        <span class="code-none">}</span></span></span></span></span></span></span></span></

And that is all, what I'm doing there is assigning the background-image attribute of all the div's inside the container to our sprite.jpg image, later, I'm assigning a background-position to display the correct portion of the whole image. Furthermore, you are getting the same result but saving some hits to your server, isn't that cool enough?

Well, that is all folks, hope you like my first article.

You can download the sample code from here

Bye bye. 

Shameless plug: You can check this article on my blog here.  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

emiaj

Web Developer

Peru Peru

Member


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionInteresting idea Pinmembered welch5:34 17 Dec '11  
AnswerRe: Interesting idea Pinassociateemiaj6:20 17 Dec '11  
GeneralBad news PinmvpPete O'Hanlon12:51 2 Jul '09  
GeneralRe: Bad news Pinassociateemiaj13:06 2 Jul '09  
GeneralRe: Bad news PinmvpPete O'Hanlon22:34 2 Jul '09  
GeneralRe: Bad news PinmemberBudha111115:35 2 Jul '09  
GeneralAnother good article Pinmemberspoodygoon10:42 2 Jul '09  
GeneralRe: Another good article Pinassociateemiaj11:23 2 Jul '09  
GeneralGood one !!! PinmemberSpunky Coder21:19 7 Apr '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120209.1 | Last Updated 2 Jul 2009
Article Copyright 2009 by emiaj
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid