utility

On CSS sprites

CSS sprites are one of the most useful tools a web designer can use to reduce load times and speed up graphics changes on hover and other events. Collective Colors is built almost entirely out of sprites; so much so that after you load the first page, there are almost no other graphics to load as you surf from page to page (excluding inline images of course). This blog entry assumes that you have a working knowledge of HTML and CSS.

So what are sprites? Sprites are essentially multiple images condensed into one. The image on the left is an example of a sprite. You may recognize this image from the secondary links that sometimes appear in the left hand sidebar. This image contains all of the sub-images required for the secondary links backgrounds.

Each row in this image covers a different section of the site: blue for about, green for portfolio, and red for blogs. Each column is used for the normal, hover, and active states of the secondary links.

To create a sprite you must consider a two basic points.

Will it be a tile? If so, on what axis will it tile?
If it is going to be used in a horizontal tile, your sprite's individual elements needs to be stacked vertically. If it is a vertical tile, you must stack them horizontally.
Will the sprite be used in an object with exacting dimensions or will the object scale?
If your sprite is used is a scaling object, be sure to put plenty of room between each element of the sprite. We will go more in depth on the mechanics of constructing sprites in another post so stay tuned.

The sprite image above is not to be used as a tile and it will be used in an object with exacting dimensions (sized anchor tags) therefore there is no need for space between each of the sprite elements. After I know these two things I can compile the image.

To compile the sprite we must first start off with a single element of the sprite. This element needs to be the exact dimensions of the object that it is to fill (in this case: width 147px by height 25px). After the first element of the sprite is made, the others are very easy modifications of the first. Once all of the pieces are created they can be assembled into a single image (see top image).

Consider the following HTML code:

<div class='secondary-links secondary-links-about'>
 <ul class="slinks" id="subnavlist">
  <li><a href="/about/design" >Design</a></li>
  <li><a href="/about/experience" >Experience</a></li>
  <li><a href="/about/consulting" >Consulting</a></li>
  <li><a href="/about/availability" >Availability</a></li>
 </ul>
</div>

I made the class "secondary-links-about" bold because it is a dynamic class. When a viewer is looking at a page in the about section that class is present as secondary-links-about. There are two other possibilities: secondary-links-portfolio and secondary-links-blogs. These changes are made possible by some clever coding in the theme's page.tpl.php file.

As you may know when using the css background property you can change the background position thusly:

.some-element {
  background: url('path-to-image.png') x-axis-offset y-axis-offset repeat-setting;
}

Background positioning with x and y axis offsets is somewhat non-intuitive. Negative offsets in the x axis offset move the background position to the right. Negative offsets in the y axis offset move the background position down. For instance, the following CSS snippet will move the background position 25 pixels to the right and 100 pixels down fron the starting point at the top left corner of the background image (0 0):

.some-element {
  background: url('path-to-image.png') -25px -100px no-repeat;
}

Now consider the following CSS code

.sidebar-content .secondary-links .slinks li {
  list-style: none;
  list-style-type: none;
  list-style-image: none;
  padding: 0 0 3px 0;
  margin: 0;
}
.sidebar-content .secondary-links .slinks li a {
  color: #FFFFFF;
  display: block;
  font-size: 15px;
  width: 132px;
/* Width + Horizontal padding = 147px */
  height: 21px;
/* Height + Vertical padding = 25px */
  position: relative;
/* IE Stinks! */
  padding: 4px 5px 0 10px;
/* Vertical padding is in bold, Horizontal is in italics */
}

/* About (blue) slinks */

.sidebar-content .secondary-links-about .slinks li a {
  background: url('images/CCSLinkBGSprites.png') 0 0 no-repeat;
}
.sidebar-content .secondary-links-about .slinks li a:hover {
  background: url('images/CCSLinkBGSprites.png') -147px 0 no-repeat;
}
.sidebar-content .secondary-links-about .slinks li a:active,
.sidebar-content .secondary-links-about .slinks li a.active {
  background: url('images/CCSLinkBGSprites.png') -294px 0 no-repeat;
}

/* Portfolio (green) slinks */

.sidebar-content .secondary-links-portfolio .slinks li a {
  background: url('images/CCSLinkBGSprites.png') 0 -25px no-repeat;
}
.sidebar-content .secondary-links-portfolio .slinks li a:hover {
  background: url('images/CCSLinkBGSprites.png') -147px -25px no-repeat;
}
.sidebar-content .secondary-links-portfolio .slinks li a:active,
.sidebar-content .secondary-links-portfolio .slinks li a.active {
  background: url('images/CCSLinkBGSprites.png') -294px -25px no-repeat;
}

/* Blog (red) slinks */

.sidebar-content .secondary-links-blogs .slinks li a {
  background: url('images/CCSLinkBGSprites.png') 0 -50px no-repeat;
}
.sidebar-content .secondary-links-blogs .slinks li a:hover {
  background: url('images/CCSLinkBGSprites.png') -147px -50px no-repeat;
}
.sidebar-content .secondary-links-blogs .slinks li a:active,
.sidebar-content .secondary-links-blogs .slinks li a.active {
  background: url('images/CCSLinkBGSprites.png') -294px -50px no-repeat;
}

Changing the x and y axis offsets are the key to using sprites in your CSS designs. As you will note in the CSS code above, the about section (blue section) always has a 0 in the second column. The reason is that the background images for the about section are all in a horizontal row. Thus, for the hover and active subclasses, only the x axis offset changes. Since we know the exact dimensions of the anchor tag as well as each element of the sprite image (147px width by 25px height), we can easily calculate what x and y offsets we need to get the proper background for each of the anchor's subclasses.

Was this helpful to you? Contact me and let me know.