Friday, February 24, 2012

CSS Sprites


The problem

You have a menu bar with the standars buttons, including the proverbial "previous / back" and "next / forward" buttons which look like...

You have been asked to improve the usability of them. In addition, your application is not coming up well in performance analysis tools. One reason for this is that many pages are downloading numerous components resulting in too many HTTP requests. It's time to consider mechanisms to reduce the number of HTTP request required to display your pages.

The solution

Well consider the usability first. The images for the buttons don't look that bad. It's obvious what they mean and what they will do, so there's not much point adding tooltips. But we could make things look sleeker with some "hovering".  What's hovering?  Hovering is a technique which dynamically changes a component when a mouse "hovers" over it. Technically, tooltips are a form of hovering but there are other types: components can change colour or light up. Let's apply some hovering magic to our prev / next buttons.  Hover your mouse over the buttons below, do it a few times and watch them glow.

So how did we do all that? Well, the first thing we do is make alternative images of our original images. This can be done using any decent editing tool: gimp, paint shop pro, take your pick - for this example, I just used Picaso. The second thing to do is to amalgamate the four separate images using a tool such as CSS Sprite generator into one single image.

Why one single image? Well that's for the performance part. HTTP requests can be expensive. We don't want to have to 4 separate HTTP requests for 4 images. So instead, we have one image which contains everything we need. This downloads all four components in one go. We then use some CSS tricks to:
  1. Pull the 2 images out of the one big sprite
  2. Switch the images to their hover versions when the mouse hovers over them
So how do we all that... time to look at some CSS.
#navlist{position:relative;}
#navlist li{margin:0;padding:0;list-style:none;position:absolute;top:0;}
#navlist li, #navlist a{height:60px;display:block;}

#prev{left:0px;width:60px;}
#prev{background:url('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTHOhAUUfvhMQd9wO68I_rFvM6N_u2oyx29R4IOGlHGdVa9rijixF2OgVDIHGZIMLucPUuXsyl0q4Whc0MpeKWCTuDsTdAnaoXlBYB6KsWRo09LNU022GecQvRQipB3TWOBq3qQVjeYTS/s200/sprite.png') 0 0;}
#prev a:hover{background: url('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTHOhAUUfvhMQd9wO68I_rFvM6N_u2oyx29R4IOGlHGdVa9rijixF2OgVDIHGZIMLucPUuXsyl0q4Whc0MpeKWCTuDsTdAnaoXlBYB6KsWRo09LNU022GecQvRQipB3TWOBq3qQVjeYTS/s200/sprite.png') -60px -60px;}

#next{left:61px;width:60px;}
#next{background:url('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTHOhAUUfvhMQd9wO68I_rFvM6N_u2oyx29R4IOGlHGdVa9rijixF2OgVDIHGZIMLucPUuXsyl0q4Whc0MpeKWCTuDsTdAnaoXlBYB6KsWRo09LNU022GecQvRQipB3TWOBq3qQVjeYTS/s200/sprite.png') 0 -60px;}
#next a:hover{background: url('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTHOhAUUfvhMQd9wO68I_rFvM6N_u2oyx29R4IOGlHGdVa9rijixF2OgVDIHGZIMLucPUuXsyl0q4Whc0MpeKWCTuDsTdAnaoXlBYB6KsWRo09LNU022GecQvRQipB3TWOBq3qQVjeYTS/s200/sprite.png') +60px 0px;}

The second half of the cake is the HTML, note the id's


Explanation
  1. The CSS shows a styled navigation list. A list with id="navlist" will reap the styled benefits.
  2. An element with id="prev" will disect up the collection of images aka the "sprite sheet" and take out the part of the image it wants i.e. the left arrow
  3. An element with id="next" take out the right arrow
  4. "prev" and "next" have hover images which are also taken from the sprite sheet and will be displayed when the mouse hovers over them.
So there we go. Better usability and better performace.  A good day's work. So any other questions? Well an obvious one would be why not just use an image map? It will also reduce HTTP requests. That's true. But, it's not as flexible as using CSS sprites. When image maps are used, the images have to be continguous. Using the CSS sprites technique, you can split them up whatever way you want. A whole bunch of images can be put onto the one sprite and then can be used together, seperate and in whatever order you want.  In fact this is how most companies used CSS sprites. They create a sprite sheet which contains various images for all parts of the web application.  Inline images are another approach. This approach will download the image in the same HTTP request as the page and thus also reduce HTTP requests but it willalso increase the size of the HTML page.  Browser support for CSS sprites approach is also better.

So, is anyone else using CSS sprites - hell yeah! Recognise anything here...


References
  1. Really interesting page about the evolution of google super sprite
  2. W3C page on CSS sprites
  3. Sprite generator

No comments:

Post a Comment