Create an Accessible Image Based Navigation
Posted Thursday, February 25th, 2010Since the launch of Hull Digital Live ’09 back in August 2009 I have been flooded with requests on how I created the graphical navigation on the web site. The answer is simple, a sprite and a dash of CSS!
This technique of image replacement can be found on a range of websites including the Apple website and Web Designer Wall, and it has a range of benefits, mainly loading time and reduction of file size.
Using the image replacement technique is very handy when each link is unique. If you notice on the Hull Digital website, each link on the navigation has its own unique background on rollover. It can be used if each link has the same interactive states but I would advice using CSS more in this case. So here is a short tutorial on how to create an accessible based navigation similar to the Hull Digital website.
All the files used in this tutorial can be found here: Download
You can view the final navigation here: Final Navigation Demo
1. Start with your sprite.
First of the whole navigation is drawn from 1 single image. This reduces the load time required and also avoids any delay on mouse over by actually loading in a new separate image.
Here is what your image would look like.

So once this image has been uploaded we need to set up the XHTML and to do this we use a standard un-ordered list with an ID.
2. The Markup
<ul id="global-nav" >
<li><a href="./">Home</a></li>
<li><a href="./about">About</a></li>
<li><a href="./contact">Contact</a></li>
</ul>
We must then give each list item an ID. This is not ideal, especially not for an ever expanding CMS driven site. But I would not recommend this technique on a dynamic or expanding menu bar anyway. This technique is ideal for smaller static sites, or menus that will not change.
So, our markup now looks something like this:
<ul id="global-nav" >
<li><a href="./" id="gn-home" >Home</a></li>
<li><a href="./about" id="gn-about" >About</a></li>
<li><a href="./contact" id="gn-contact" >Contact</a></li>
</ul>
Now we have our markup we need to figure out how we are going to insert our image. There are many different ways of doing this. The easiest is to display each element as a block element, add the image as a background image and nudge the text out of the way using either padding or a negative text-indent through CSS. This works and works well, however it is not particularly accessible.
You see, if a user has their images switched off on their browser, there will be no text to display, therefore making the navigation inaccessible.
So to counter this we must play around with an empty span which we embed within the <a href> element. Again, empty code tags not great! But to achieve the desired effect it is really the best and most effective way before looking at CSS3.
So our markup ends up looking like this.
<ul id="global-nav" >
<li><a href="./" id="gn-home" >Home<span></span></a></li>
<li><a href="./about" id="gn-about" >About<span></span></a></li>
<li><a href="./contact" id="gn-contact" >Contact<span></span></a></li>
</ul>
And that’s it! Pretty clean huh? Well obviously other than the empty span!
Anyway, lets move on to styling this bad boy.
3. The Style.
Ok, now we have our markup and our image, all we have to do is style it. We firstly need to make sure all the links sit in-line rather than top to bottom, we then need to make sure they are set as block elements so we can actually see the background image, and finally we need to sort out positioning so we can play around with our span.
So, for the initial styling. We need to add a background to the main page to allow the images to blend in, I have chosen a simple noise texture for this example. All image files can be found in the download or in use on the demo page.
body{
background:url('images/BG-main.jpg');
}
We then set up the un-ordered list with ID ‘global-nav’ with a set height and width. This allows us to clear any content beneath as we will be using floats on our blocked list objects.
#global-nav{
display:block;
height:33px;
list-style:none;
}
We then need to look at the standard list item. We won’t look at styling sizes and particulars yet as this will be done with the specific IDs. We can also within this single tag add some global styling to the links and the spans as they will all warrant the same style.
#global-nav li, #global-nav li a, #global-nav li a span{
float:left;
height:33px;
}
We now need to make sure our hyperlink has a relative position. We do this because we are going to position our span absolutely over our hyperlink, effectively masking the text behind with the image.
#global-nav li a{
position:relative;
text-align:center;
}
Now we position the span. As we have added a relative position to the surrounding hyperlink and set specific sizes, add an absolutely positioned element within this will be simple and cross browser compatible. We also at this stage include our sprite which will apply the background image to each span on a single load.
#global-nav li a span{
position:absolute;
top:0;
left:0;
background:url('images/BG-global-nav.jpg') no-repeat left top;
}
Now as each of our hyperlinks are different, they all need individually styled elements applied to them. So for this next step we apply two styles, one to the hyperlink itself and one to the span.
#global-nav li a#gn-home, #global-nav li a#gn-home span{
width:102px;
}
#global-nav li a#gn-about, #global-nav li a#gn-about span{
width:109px;
}
#global-nav li a#gn-contact, #global-nav li a#gn-contact span{
width:135px;
}
As you can see from this code we have applied a width to each span and hyperlink to define the exact widths for each item.
So if you check your build at the moment, you should see everything taking shape, but each link will have the ‘Home’ image visible. This is because we need to do our final step which is to position each item according to the size of the link. This is where a bit of simple maths comes in!
Take the image below as a guide for your sizes. The space around the sprite has been increased so the guides can be visible.

Once you have worked out the widths of your navigation elements, it is then a simple case of applying a minus value each time you add a link. Within the style this looks like the following:
#global-nav li a#gn-home span{
background-position:left top;
}
#global-nav li a#gn-about span{
background-position:-102px top;
}
#global-nav li a#gn-contact span{
background-position:-211px top;
}
So as you can see, the first link or the ‘home’ link image is positioned ‘left’ ‘top’ or ’0 0′. The next link along is then nudged to the left by the exact amount as the first link is wide, in this case 102px.
The next figure is then created by adding the first two widths together, in this case 102px + 109px = 211px. For longer navigation bars you would simply continue this trend right the way through to however many links you want on the page.
So re-checking the example you should see that each link now has the correct ‘inactive’ state applied. Now we simply need to add a hover state, and this again is really simple. We need to add the hover state to the ‘href’ rather than the ‘span’ so it will be compatible with the good old crummy IE6!
So your final addition to your CSS would look like this:
#global-nav li a#gn-home:hover span{
background-position:left bottom;
}
#global-nav li a#gn-about:hover span{
background-position:-102px bottom;
}
#global-nav li a#gn-contact:hover span{
background-position:-211px bottom;
}
All we have done here is change the value ‘top’ to the value ‘bottom’ meaning the hover over state looks visible when the user hovers over the link.
The Dreaded IE6!
There is one down side to this swift little technique and that is IE6 will not support the hover of any html element other than a link, so our neat little CSS technique just won’t cut it and you will need to pull in a little Javascript. Luckily there is a script at hand, and it is know as ‘Whatever:hover’. It can be downloaded here and it has simple installation instructions.
So that’s it! Give it a go yourself, making an accessible image based website navigation is simple! Make sure to view the fully working demo and download the files!



March 13th, 2010 at 1:21 pm
quite structured recap on css image sprites. The IE7 / IE8 script by Dean Edwards should fix the the IE6 issue.
March 19th, 2010 at 12:01 am
THANKS HEAPS :D
TEEEEEEEEEEEEEHEEEEEEEEEEE
March 20th, 2010 at 11:34 am
Very clear, good article :)
May 26th, 2010 at 4:00 am
Thanks for the tutorial. I absolutely love your websites and often refer to them for inspiration in designs.
May 29th, 2010 at 7:47 pm
Great tutorials I’ve been looking for something like this!
June 15th, 2010 at 9:20 am
Excellent tutorial, very easy to understand
June 28th, 2010 at 4:07 pm
Great tutorial, simple but beautiful css image menu, love it.
June 29th, 2010 at 12:52 pm
found your site on del.icio.us today and really liked it.. i bookmarked it and will be back to check it out some more later