demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

  • rss
  • about
  • book
  • mail

CSS Sprites for the Modern Era: Refined, Animated, and Semantic

css / sprites

Estimated reading time: 4 minutes, 39 seconds

CSS sprites are now almost a decade old. The core concept of the technique – creating a “panel” of images that are displayed as a background in links and moved to show different icons – is enshrined in thousands of web pages and dozens of frameworks.

As a concept, CSS sprites are very powerful: one image loaded for all buttons on a site cuts page loading times by eliminating multiple server requests for separate files. But practically, I’ve always had several issues with them:

  1. Sprite panels are complex to make, requiring at least two different images for each icon state.
  2. There is no alt attribute for background images: so if the sprite does not load, there is nothing to click on in the navigation.
  3. Similarly, without an alt attribute CSS Sprites are not .
  4. Without alternative text, search engines lack an understanding of the purpose of links.
  5. CSS sprites could not be animated, unless one tried to turn an animated GIF into a sprite (:: shudder ::)

  6. Making two versions of each icon doubles the panel size, increasing load time and complicating the CSS.
  7. The CSS to make a sprite work was somewhat complex, requiring multiple sets of coordinates.

In considering the redesign of this blog (currently under development) I very much wanted to update the idea of CSS sprites for the 21st century, eliminating the drawbacks of the traditional approach. I call my solution “CSS3 Sprites”.  You can see an oversized example in the header image for this article.

The process to create a CSS3 sprite panel is just nine steps:

  1. Make a sprite panel as you would traditionally, but the with icons drawn in a single state only (a monochrome theme will probably work best.). Optional: make the sprite panel twice as large as what will be actually displayed on the page.

  2. Export the panel. If you’ve taken the optional step above, export the panel in two sizes: one at the final size of the collective icons as displayed by default on the page, say 150px × 150px, and another twice as large (ie. 300px by 300px). For this example I’ll call the first image temp-sprite-panel and the second sprite-panel. (I’d also recommend that you export the image(s) as transparent PNG files for the most flexibility).

  3. Create an unordered list for the navigation. (You might want to look at examples I’ve talked about previously in this blog if this concept is unfamiliar to you.)

  4. Place the temp-sprite-panel.png file as an img tag inside links that are within each item in the list, as you normally would. Include alt and title attribute values that are appropriate for the icon that will be visible at that point.

  5. Attach a class to the unordered list. The class will be used for general shared properties of all uses of the sprite panel.

    At this stage, our HTML code should look something like this. (I have removed optional closing tags to save on space).

    <ul class=sprites>
    <li><a href=#><img src=temp-sprite-panel.png alt=RSS></a>
    <li><a href=#><img src=temp-sprite-panel.png alt=About></a>
    <li><a href=#><img src=temp-sprite-panel.png alt="Book Mode"></a>
    </ul>

    Right now, each list item link contains a copy of the entire visible sprite panel image, with the list items positioned one underneath the other. We are going to put the list items side by side while reducing the opacity of the image used in each link, to create a default “inactive” state for every icon. In our CSS:

    ul.sprites li { display: inline; }
    ul.sprites li a img { position: absolute; opacity: 0.4; width: 150px; height: 76px; }

    (Note that I've placed the size of the temp-sprite-panel.png file in the CSS).

  6. Next, we will visually restrict each image to show only the appropriate icon by using the clip property. clip requires that its element be positioned absolutely, which is why we applied it in the CSS above. We’ll apply the CSS by referencing the alt attribute of each sprite.

    Remember that clip uses offsets from the top and left and edges of the image to determine which portion to show. You may want to open up your sprite panel in PhotoShop to determine these numbers. For our example, they might be something like:

    img[alt="RSS"] { clip: rect(54px,21px,76px,0px); }
    img[alt="About"] { clip: rect(54px,47px,76px,25px); }
    img[alt="Book Mode"] { clip: rect(54px,75px,76px,48px); }
  7. Because clipped images have no “height” per se, we need to set a height on the navigation list. This should be the same as the height of all uses of CSS3 sprite navigation on our site (as the icons are all the same height), so we can put that on our class for our list:

    ul.sprites { height: 27px; }
  8. With everything now in place, the last thing we need to do is create the “active” state for each icon, via a hover pseudo-selector:

    ul.sprites a:hover img { opacity: 1; }

    That’s it! Each sprite is now accessible, as each has its own unique alt value. If you wanted to animate the sprite transition:

    ul.sprites li a img { position: absolute; opacity: 0.4; width: 150px; height: 76px; transition: all 0.5s linear; }

    If you want to retain greater image quality during page zooms of the sprite panel on browsers or mobile devices, substitute sprite-panel.png for temp-sprite-panel.png in the HTML, without changing the CSS. The larger image will be shrunk down to the size of the former, smaller panel, then the clip(s) will be applied. When the page zooms, each icon will look sharper.

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.