• CSS Background Image Sprites: A Beginner’s Guide

  • By: Jarod Taylor | Category: HTML & CSS
  • Without regurgitating too much history behind image sprites and how and why we should use them, we're going to create something practical that you can implement into your projects immediately. There are several resources and tutorials already covering what image sprites are and even how we should use them. Just google "CSS Image Sprites" and you'll return more than 2000 results. We're going to skip the history lesson and get you started using CSS image sprites today.

    Get SourceView Demo

    Crash Course

    As I said, without repeating too much of what's been said several times before, I'm going to briefly explain to you what a CSS image sprite is and how they work. If you want to skip this brief CSS sprites crash course, skip ahead.

    What is a CSS image sprite?

    It is a method of using CSS to optimize the use of background images in websites to not only reduce HTTP requests but also file sizes. Which which makes your page-viewers happy since your pages load faster.

    No, seriously, what is a CSS image sprite?

    Basically, you take multiple images and combine them into one single image (sometimes referred to as the "master image"). You then use the CSS background-position property to tell the browser where to position the image in the viewport of the containing element.

    Wait, you lost me at background-position and viewport!

    As you probably know, the background-position property accepts two kinds of values: CSS units (px, em, %, etc.) and keywords. The element's viewport loosely refers to the area of a containing element in which you can physically see. It usually depends on several things like width, height, padding, etc. Take a look at the image below.

    tutorial image

    So we have a master image with a width of 240px and a height of 80px. This image contains 3 icons, so essentially, each icon is 80px wide (240px ÷ 3 = 80px) with a height of 80px as well. We also have a block element (in this case a div), which also has a width of 80px and a height of 80px. This div is where our background image is going to live.

    Now let's code some quick CSS and HTML to render our example. You can get the three-icons.gif image here.

    <!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>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Simple CSS Background Image Sprite</title>
    <style type="text/css">
    div.one {
    	background-image: url(images/three-icons.gif);
    	background-position: 0 0;
    	background-repeat: no-repeat;
    	width: 80px;
    	height: 80px;
    }
    </style>
    </head>
    
    <body>
    <div class="one"> </div>
    </body>
    </html>
    

    What we have done here is very basic. We've declared the div element's width to be 80px and its height to be 80px as well. We've declared our background's position to have an x-position of 0 and a y-position of 0. The x (first) value is the horizontal position and the y (second value) is the vertical position. We've also set the background-repeat to no-repeat. With the code above, this is what we get. As you would expect, the background is displaying the icon on the far left (the clock) of our master image. This is because setting both our x and y positions to 0 is the same as setting the x-position to left and the y-position to top.

    So, how do we get the other icons to show?

    Now keep in mind all our icons are the same height (80px), so we won't need to adjust the y-position. In order for our div to display the different backgrounds, all we need to do is shift the background's x-position to the left. Well, if 0 is the absolute left position, how do we do that? Good question! It's easy, we just give it a negative position. Let's take a look here.

    tutorial image

    As you can see, we can simply adjust the x-position of the background using any of the CSS units (px, %, em, etc.) or the key words (left, center, right, top, bottom).

    So let's try this out. Add the following styles right below your div.one styles.

    
    div.two {
    	background-image: url(images/three-icons.gif);
    	background-position: -80px 0;
    	background-repeat: no-repeat;
    	width: 80px;
    	height: 80px;
    }
    
    div.three {
    	background-image: url(images/three-icons.gif);
    	background-position: -160px 0;
    	background-repeat: no-repeat;
    	width: 80px;
    	height: 80px;
    }
    
    

    Now add the two more divs to your body and you should have something like this:

    <!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>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Simple CSS Background Image Sprite</title>
    <style type="text/css">
    div.one {
    	background-image: url(images/three-icons.gif);
    	background-position: 0 0;
    	background-repeat: no-repeat;
    	width: 80px;
    	height: 80px;
    	margin-bottom: 10px;
    }
    
    div.two {
    	background-image: url(images/three-icons.gif);
    	background-position: -80px 0;
    	background-repeat: no-repeat;
    	width: 80px;
    	height: 80px;
    	margin-bottom: 10px;
    }
    
    div.three {
    	background-image: url(images/three-icons.gif);
    	background-position: -160px 0;
    	background-repeat: no-repeat;
    	width: 80px;
    	height: 80px;
    	margin-bottom: 10px;
    }
    </style>
    </head>
    
    <body>
    <div class="one"> </div>
    <div class="two"> </div>
    <div class="three"> </div>
    </body>
    </html>
    

    First thing some of you will notice is the CSS is a bit bulky and could definitely use some cleanup to make the code more compact, efficient and cleaner; we'll get to that in a minute. I also applied a 10px margin to the bottom of each of the icons, to give them some breathing room. Let's take a look at what we have.

    It's like magic! It looks like we used CSS to cut our image into 3 different images. If you're using Firefox, you can right-click on each and View Background Image.

    Before we start with something practical , let me touch briefly on a topic I like to call CSS code refactoring. As I said above, our CSS could use some TLC. By grouping CSS selectors and using CSS shorthand properties, we can seriously condense our current code.

    All three of our divs basically share the same properties. The only difference is the background-position properties. So let's group the three div selectors and adjust the background-position properties accordingly.

    div.one, div.two, div.three {
    	background-image: url(images/three-icons.gif);
    	background-position: 0 0;
    	background-repeat: no-repeat;
    	width: 80px;
    	height: 80px;
    	margin-bottom: 10px;
    }
    
    div.two {
    	background-position: -80px 0;
    }
    
    div.three {
    	background-position: -160px 0;
    }
    

    Now, that's much leaner! Let's really thin it out now by combining the background properties into shorthand properties.

    background: url(images/three-icons.gif) no-repeat 0 0;
    

    Lean, clean, sprite machine

    <!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>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Simple CSS Background Image Sprite</title>
    <style type="text/css">
    div.one, div.two, div.three {
    	background: url(images/three-icons.gif) no-repeat 0 0;
    	width: 80px;
    	height: 80px;
    	margin-bottom: 10px;
    }
    
    div.two {
    	background-position: -80px 0;
    }
    
    div.three {
    	background-position: -160px 0;
    }
    
    </style>
    </head>
    
    <body>
    <div class="one"> </div>
    <div class="two"> </div>
    <div class="three"> </div>
    </body>
    </html>
    

    That's it! That's how CSS image sprites work. Now, let's get some practical use out of this!

    Introduction

    Now that you have a pretty good understanding of what CSS Sprites are and how they work, let's take it a little bit further and put it to good use.

    In the Crash Course, we used one master image to house 3 icons. In this example we're going to elaborate on that by implementing 8 icons into one image.

    tutorial image

    There are several techniques and levels of complexity involved in utilizing one single background image (master image) for multiple destinations in a given web application. Due to the nature of this article, we'll stick with learning the basics, building a foundation for understanding the vast possibilities in using CSS image sprites, and get you using them in your current projects. Once you have your "Ah hah!" moment, you'll be ready to explore a plethora of possibilities. Let me first give you a heads up on what's to come in the rest of this tutorial.

    Steps
    1. Set up our directories and prepare for our layout
    2. Prepare our icons and create our master image
    3. Write our HTML
    4. Implement our CSS

    Before we get started, you'll need to download the free Simplistica Icon Set created by Dryicons.com.

    Set Up Our Directories

    For this tutorial, I'm using a standard directory setup. To avoid confusion I recommend using the same.

    1. Create a directory/folder and name it iconsprites
    2. Create a new folder inside iconsprites and name it css
    3. Create a new folder inside iconsprites and name it images

    You may be thinking to yourself, "why do we need all these directories when each folder is only going to contain 1 file?", and I understand it may seem a bit overkill, but it's a good idea to get in the habit of setting up your structure this way. If you have a site that is large, it's imperative you set it up in a way that's relatively intuitive and easily manageable.

    Create Our Master Image

    Let's fire up Photoshop and get this started! If you're not using photoshop, you should still be able to follow this tutorial easily with whatever graphics editing program you're using.

    Now, as I said in the beginning, we're going to use 8 icons in this tutorial. Go ahead and choose the 8 icons you want to use out of the Simplistica Icon Set. I'm going to use the 32px icons. You can see which ones I'm using in the demo.

    Each icon is 32px × 32px so we need to decide how we're going to align these icons in a way that's feasible. We can choose to align the icons horizontally and adjust the x-position to position our icons, or we can align them vertically and adjust the y-position accordingly. Believe it or not, this is an important decision.

    If you remember in the crash course we were using a master image with a width of 240px, holding 3 icons with widths of 80px each, and we were positioning them in a div with a declared width of 80px as well. In that particular situation, it wouldn't really matter whether we aligned the icons horizontally or vertically -- because the containing element had a declared width and height of 80px. In a situation where the width or height of an element can change, funny things can happen. Let's take a look at our earlier example, without declared dimensions.

    <!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>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Simple CSS Background Image Sprite</title>
    <style type="text/css">
    div.one, div.two, div.three {
    	background: url(images/three-icons.gif) no-repeat 0 0;
    	margin-bottom: 10px;
    }
    
    div.two {
    	background-position: -80px 0;
    }
    
    div.three {
    	background-position: -160px 0;
    }
    
    </style>
    </head>
    
    <div class="one">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
    <div class="two">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
    <div class="three">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
    </body>
    </html>
    

    I also put some filler text in each of the divs for a better example of what can happen. Take a look at what happens when we remove the dimensions from our containing div. Does this mean you have to declare a width and a height on all the elements you're planning to use a background image sprite on? Not necessarily, you just have to keep these things in mind when deciding how you're going to position the images in your sprite.

    In our 8 icon layout, we'll be creating an unordered list, where each list item will contain a heading and some text. Let's take a quick look at what we're going to be marking up.

    tutorial image

    We need to decide what element is going to contain our background images. Our icons have a width of 32px and a height of 32px as well. If we apply our background images to our list-items (li tags) we will have to worry about the height and width of the entire li element growing. Because our li element contains our h2 elements and p elements, it will grow whenever these elements grow. That would be difficult to maintain. So that leaves us with either the h2 element or the p element. Based on the design mockup, the h2 element looks like it's the best home for our background sprite.

    Let's fire up photoshop and get our master image ready to go. We've established that our h2 element will be the home to our background image sprite. Because our h2 element will grow more in width than it will in height, we'll align our icons vertically.

    Get Master Image Ready
    1. Create a new photoshop document with a width of 32px and a height of 512px.
    2. Fill the background with #efefef.
    3. Create the following horizontal guides (total 7):
      • 64px
      • 128px
      • 192px
      • 256px
      • 320px
      • 384px
      • 448px
    4. Align an icon to each of the guides you just created (it helps if you use the alignment tools in Photoshop, and the "Snap to Guide" option is checked in your View options).

      tutorial image
    5. Save your image as a gif or png in your iconsprites/images folder.
    What we created

    You may be asking, why we created an image with a height of 512px when our 8 images combined height only adds up to 256px. The reason we did this, is because we want to allow some additional space between our icons for browser inconsistencies as well as the fact that our containing element could unexpectedly grow -- causing the the same problems to happen as it did in our first example.

    Write our HTML

    We're going to use some very simple, semantic markup for our example. In this case we're going to be using an unordered list with fixed widths on the li elements. Doing this will allow for us to float the li elements, making it easy to style and implement. Please keep in mind, in this example, we're assuming the content within the li elements will not grow. For instance, if the h2 text were to wrap to a new line, it could cause some funny things to happen. I discuss this a little further at the end of this tutorial.

    Here's our HTML:

    <!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>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>CSS Background Image Sprites: A Beginner's Guide</title>
    <link href="css/styles.css" rel="stylesheet" type="text/css" />
    </head>
    
    <body>
    <ul id="content-list">
        	<li>
            	<h2 id="home">Sed Perspiciatis Unde</h2>
                <p>Donec blandit massa sed nisl. Suspendisse sollicitudin, eros nec adipiscing placerat, dui risus mattis augue, vitae euismod enim lorem sed risus.</p>
            </li>
            <li>
            	<h2 id="calendar">Proin Elementum Lacinia</h2>
                <p>Fusce eleifend. Sed tempus, turpis vitae ornare sollicitudin, metus risus volutpat purus, ac commodo arcu odio a nisi.</p>
            </li>
            <li>
            	<h2 id="info">Phasellus Dolor Nulla</h2>
                <p>Vestibulum iaculis nulla viverra enim. Nam vehicula. Phasellus volutpat felis vitae tortor. Nulla interdum leo vestibulum mauris.</p>
            </li>
            <li>
            	<h2 id="user">Cras Feugiat Ipsum</h2>
                <p>Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae.</p>
            </li>
            <li>
            	<h2 id="monitor">Morbi Volutpat Lacinia</h2>
                <p>Praesent aliquam, nunc quis ornare feugiat, sapien urna tempus mi, eget facilisis orci diam quis lacus. Sed dui. Curabitur sed augue id arcu.</p>
            </li>
            <li>
            	<h2 id="rss">Aliquam Neque Iaculis</h2>
                <p>Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores.</p>
            </li>
            <li>
            	<h2 id="comment">Donec Dignissim Lectus</h2>
                <p>Fusce sed arcu a sapien sodales molestie. Morbi quis massa ut ipsum ultrices accumsan. Fusce pretium eu mi. Proin at nisi at dolor egestas mollis.</p>
            </li>
            <li>
            	<h2 id="mail">Magna Lacus Tincidunt</h2>
                <p>Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat assumenda est.</p>
            </li>           
        </ul>
    </body>
    </html>
    
    

    Save your file as index.html in the iconsprites folder.

    As I said, pretty self explanatory markup here. If you were to look at it in a browser right now, it would look pretty drab and uninteresting, but we're going to fix that next!

    Make It Pretty

    We're going to start out with some basic styles to get our page ready for our content. Create a new CSS file and place the following styles in the top of your stylesheet.

    * {
    	margin: 0; 
    	padding: 0;
    }
    
    body {
    	background-color: #efefef;
    	font: 12px Arial, Helvetica, sans-serif;
    	color: #646579;
    }
    

    We first start off with a generic styles reset. I would not generally recommend this method of using a CSS Reset, however it's good practice to utilize some sort of reset to eliminate a number browser inconsistencies. Using the universal selector and zeroing out all default margin and padding settings will suffice for the demonstration. After our reset we declared some basic body styles to define the color and font properties.

    Now let's get to styling the good stuff. We'll start off with our unordered list and its basic properties. Place these styles under your body styles.

    ul#content-list {
    	list-style: none;
    	width: 720px;
    	margin: 100px auto;
    }
    
    ul#content-list li{
    	width: 325px;
    	float: left;
    	margin: 0 35px 15px 0;
    }
    

    We've set our unordered list to have a list-style of none (removes the bullets). We've declared its width to be 720px, gave it a top and bottom margin of 100px, and set the left and right margins to auto in order to center it in the browser.

    With our li elements, we've declared a width of 325px and set them to float: left. Now, because we've declared a width of 720px on its parent element (ul#content-list) -- it will only allow 2 li elements to fit in a row before it bumps the third li element below. I like to call this my "pseudo columns" technique. It's an effective and useful way of laying out elements, however it has its drawbacks; in this particular demonstration it works perfect. Take a look at what our layout looks like now.

    Let's get the general h2 styles declared and see what we get. Add this below the styles you just created.

    ul#content-list li h2{
    	color: #264772;
    	font-size: 20px;
    	background: url(../images/icons-bg.png) no-repeat;
    	padding: 12px 0 0 42px;
    }
    

    The important property declaration here is the padding. First of all, we added a top padding of 12px to make the minimum height of our h2 elements equal to the height of our icons (32px). With the font size being declared at 20px, and a top padding of 12px, we've reached our 32px minimum. We've also put some padding on the left of 42px. This will push the text over the 32px required to show the icon, as well as an additional 10px for breathing room. If you're not clear on what the padding did, just play with the numbers a bit and see what you get.

    You should now have something similar to this:

    tutorial image

    We're almost there, but not quite. Obviously, we need to set our background-position properties to position our icons accordingly. If you remember, when we created our master image, we created 7 horizontal guides on our image. These guides not only helped us align our icons in the master image, but these numbers will play a role in our CSS as well.

    Let's take a look at them again.

    1. 64px
    2. 128px
    3. 192px
    4. 256px
    5. 320px
    6. 384px
    7. 448px

    These numbers will look familiar in our next addition to our stylesheet.

    /*Each of our icons in the master image are 64px below the icon above it. We just need to increment the y position -64px for each icon */
    
    ul#content-list li h2#home{
    	background-position: 0 0; /* Icon is at the top of our master image */
    }
    
    ul#content-list li h2#calendar{
    	background-position: 0 -64px;
    }
    
    ul#content-list li h2#info{
    	background-position: 0 -128px;
    }
    
    ul#content-list li h2#user{
    	background-position: 0 -192px;
    }
    
    ul#content-list li h2#monitor{
    	background-position: 0 -256px;
    }
    
    ul#content-list li h2#rss{
    	background-position: 0 -320px;
    }
    
    ul#content-list li h2#comment{
    	background-position: 0 -384px;
    }
    
    ul#content-list li h2#mail{
    	background-position: 0 -448px;
    }
    

    Remember, the second value of the background-position property represents the y position, which adjusts the vertical placement of our background image. We simply needed to use the same numbers we used in our master image when we created the horizontal guides.

    We're almost done! If you take a look at what we have now, you'll notice the only thing needing some adjustments is the text under each of the headings.

    ul#content-list li p{
    	margin-left: 42px;
    }
    

    And there we have it! Take a look at what you have now.

    Final Thoughts

    This was a very basic demonstration of what you can achieve using CSS background image sprites. There are some very creative techniques being used by CSS junkies all over the web. Some of the most well known web applications on the web now are using master images with more than 100 different images included in them.

    Let's take a look at a few of the more known web apps using CSS image sprites today.

    Amazon
    tutorial image
    Yahoo
    tutorial image
    Apple
    tutorial image

    These are just a handful of the millions of sites using CSS image sprites today. The purpose of this tutorial was to give an in depth introduction to CSS image sprites and a practical example of how you could use them in your projects today. Now that you have a general understanding of what CSS image sprites are and how to use the background-position property, you're ready to explore the many possibilities of using them.

    Ready For More?

    Here are some great articles about CSS image sprites worth checking out.

    Some Quirks In Our Demo

    In this particular tutorial, we used what I called "pseudo-columns" by floating fixed width li elements. While this technique certainly comes in handy, it does come with its quirks as well. For instance, if you were to make your title tags long enough to wrap to a new line, it will push your content down and cause your li elements to re-align as well. It's very similar to the way columns and rows behave in an HTML table. In our demonstration, our content is static and doesn't fluctuate in size. This works for this type of layout, however, if you plan to use this type of layout in your project(s) and there's a possibility the content will grow, you're better off using a two-column layout. Also, if your h2 elements grow long enough in height, they will start to reveal your other icons. To avoid this, create a larger gap in between your icons in the master image.

    Goodbye

    I hope you enjoyed reading this article. If you have any questions, concerns, or issues - please ask in the comments. This way, we can share it with others that may be having the same problems. Thanks for reading!