Free! CSS Sprites: Image Slicing’s Kiss of Death
In this free article Dave Shea shows how to use an innovative new CSS technique which he calls CSS Sprites that works in all modern browsers (except Opera 6), and replaces old-school image slicing and dicing (and the necessary JavaScript) with standard CSS and HTML lists.
This article was originally published by A List Apart and is reproduced by kind permission. It's copyright © 1998–2004 A List Apart Magazine, Happy Cog Studios, and Dave Shea.
Applying the CSS
With those basic building blocks, it's time to build the CSS. A quick note before we start — because of an IE glitch, we'll be tiling the after image on top of the before image when we need it, instead of replacing one with the other. The result makes no real visual difference if we line them up precisely, but this method avoids what otherwise would be an obvious "flicker" effect that we don't want.
#skyline {
width: 400px; height: 200px;
background: url(test-3.jpg);
margin: 10px auto; padding:
0;
position: relative;}
#skyline li {
margin: 0; padding: 0; list-style:
none;
position: absolute; top: 0;}
#skyline li, #skyline a {
height: 200px; display: block;}
Counter-intuitively, we're not assigning the before image to the links at all, it's applied to the <ul> instead. You'll see why in a moment.
The rest of the CSS in the above example sets things like the dimensions of the #skyline block and the list items, starting positions for the list items, and it turns off the unwanted list bullets.
We'll be leaving the links themselves as empty, transparent blocks (though with specific dimensions) to trigger the link activity, and position them using the containing <li>s. If we were to position the links themselves and effectively ignore the <li>s, we'd start seeing errors in older browsers, so let's avoid this.
Positioning the links
The <li>
s are absolutely positioned, so why aren't they
at the top of the browser window? A quirky but useful property of positioned
elements is that all descendent elements contained within them base their
absolute position not off the corners of the browser window, but off the corners
of the nearest positioned ancestor element. The upshot of this is that since
we applied position: relative;
to #skyline
, we're
able to absolutely position the <li>
s from the top left
corner of #skyline
itself.
#panel1b {left: 0; width: 95px;}
#panel2b {left: 96px; width: 75px;}
#panel3b {left: 172px; width: 110px;}
#panel4b {left: 283px; width: 117px;}
So #panel1
isn't horizontally positioned at all, #panel2b
is positioned 96px to the left of #skyline
's left edge, and so
on. We assigned the links a display: block
; value and the same
height as the <li>
s in the past listing, so they'll end
up filling their containing <li>
s, which is exactly what
we want.
At this point we have a basic image map with links, but no :hover
states:
It's probably easier to see what's happening with borders turned on:
Bruce Lawson
I'm the brand manager of glasshaus, a publishing company specialising in books for web professionals. We've a series for dreamweaver professionals - the dreamweaver pro series.