Semantic and Gorgeous Navigation Bars
So I haven’t written in a bit, what with the Holiday Slump and all, and I’ve been thinking about what my next tutorial should be. Lots of complicated ideas have been running through my head and then yesterday, while I was working on a new project, it occured to me that the there is something I do almost every time I code a website, and that is to create a semantic navbar – one that often displays as gorgeous imagery but is in fact coded with a simple unordered list. It occured to me that perhaps not everyone knows how to do it. So, while I know it’s been blogged about before, I’m going to offer my method for accomplishing this every-day task.

The Basic Markup
:x:
I give the list an ID (mNav for Main Navigation) and give each link an ID as well. Then I wrap a span around all text so I can hide it later. Finally I use a clearing span at the end of the last LI because I am going to float the links. I like to use this method of clearing floats (when overflow:auto) doesn’t seem to work because it is relatively little markup, has no effects on unstyled documents, and doesn’t require a lot of fancy css hacks.
<ul id="mNav">
<li>Find a Person</li>
<li>Find a Skill</li>
<li>Find an Interest</li>
<li>Find a Project</li>
<li>Find Cool Stuff</li>
</ul>
:c:
The span.clear definitions ensure your floats get cleared with no extra space being taken up. I give the nav ul some margin and
instruct the LIs to display as inline so that they will lay next to each other horizontally. Then I give the links a display of block so that I can assign width and height to them and then, of course, since they are now block-level elements I have to float them so they will also lay next to one another horizontally. Next I give them the height of all my nav images and specify background properties that will be the same for all links. Finally I hide the text.
span.clear {
display:block;
height:1px;
line-height:1px;
font-size:1px;
margin-top:-1px;
clear:both;
}
/* --
***** Main Nav
--------------------------------------*/
#mNav {
margin:12px 0 0 8px;
}
#mNav li {
display:inline;
}
#mNav a {
display:block;
float:left;
height:44px;
background-repeat:no-repeat;
background-position:top left;
}
#mNav a span {
display:none;
}
The Images
Saving the Images
I created (from the PSD provided to me by Sparkplug, who did the actual design on this site) three image files for the Off, Hover, and On states of all nav links.



Then I slice the images into buttons and save them.

The CSS
I give each link a width and a background image, then define alternate images for the hover state or if the “on” class is applied.
#mNav a#mNav_person {
width:154px;
background-image:url(../_images/mNav/off/person.gif);
}
#mNav a#mNav_person:hover {
background-image:url(../_images/mNav/hover/person.gif);
}
#mNav a#mNav_person.on {
background-image:url(../_images/mNav/on/person.gif);
}
#mNav a#mNav_skill {
width:153px;
background-image:url(../_images/mNav/off/skill.gif);
}
#mNav a#mNav_skill:hover {
background-image:url(../_images/mNav/hover/skill.gif);
}
#mNav a#mNav_skill.on {
background-image:url(../_images/mNav/on/skill.gif);
}
#mNav a#mNav_interest {
width:152px;
background-image:url(../_images/mNav/off/interest.gif);
}
#mNav a#mNav_interest:hover {
background-image:url(../_images/mNav/hover/interest.gif);
}
#mNav a#mNav_interest.on {
background-image:url(../_images/mNav/on/interest.gif);
}
#mNav a#mNav_project {
width:154px;
background-image:url(../_images/mNav/off/project.gif);
}
#mNav a#mNav_project:hover {
background-image:url(../_images/mNav/hover/project.gif);
}
#mNav a#mNav_project.on {
background-image:url(../_images/mNav/on/project.gif);
}
#mNav a#mNav_stuff {
width:155px;
background-image:url(../_images/mNav/off/stuff.gif);
}
#mNav a#mNav_stuff:hover {
background-image:url(../_images/mNav/hover/stuff.gif);
}
#mNav a#mNav_stuff.on {
background-image:url(../_images/mNav/on/stuff.gif);
}
Preloading the Images
If I keep writing articles one thing will become quickly apparent … I’m no Javascript maven! I do what I can, and can usually come up with solutions, but I’m fairly certain they’re not always the most elegant or appropriate. That being said, this is how I preload the hover images so that there is no flicker the first time they are moused over.
The Script
Just define the image number (pic1), the image dimentions in pixels (154,4), and the source (pic1.src=”…”) for each of the images that you want to preload. Then simply link to this code in your header and that’s it!
pic1= new Image(154,4);
pic1.src="../_images/mNav/hover/person.gif";
pic2= new Image(153,44);
pic2.src="../_images/mNav/hover/skill.gif";
pic3= new Image(152,44);
pic3.src="../_images/mNav/hover/interest.gif";
pic4= new Image(154,44);
pic4.src="../_images/mNav/hover/project.gif";
pic5= new Image(155,44);
pic5.src="../_images/mNav/hover/stuff.gif";
That’s Wrap!
Check out the finished product and enjoy.
January 3rd, 2006 at 1:33 pm
Hi Mani – Happy New Year.
No need to preload the images! Just put the three images, (off, hover, on), side by side into one image. You can then change the
background-positionof the image in your CSS rules for#mNav a#mNav_whatever, rather than thebackground-imageitself.Fewer images; no preloading or scripting necessary.
January 3rd, 2006 at 1:36 pm
Awsome, David!
I love it!!!
P.S. – I see I need to tweak my code styles for comments, eh? ;o)
January 4th, 2006 at 11:22 am
It’s a beautiful nav bar, but is there a way to prevent the major hover flicker experienced in IE? It works great in FF, but 62% of our clients are in IE 6.
January 4th, 2006 at 11:57 am
Hmmm … I’m not experiencing that in IE over here on my end and have not heard any complaints from clients about this. Perhaps there was something glitchy with the preload script.
In any case, I bet David’s elegant solution of using one image instead of three would solve any of those preload issues.
Thanks again for that, David! ;o)
January 4th, 2006 at 2:46 pm
dRussell – This is a known problem when using background images and dynamic effects in IE. Unfortunately, this can only be fixed on your server.
See this explanation and solution from Dean Edwards.
January 5th, 2006 at 3:31 pm
Unfortunately, I do see the flicker in IE 6 on your great looking nav bar. I have my browser set to “check for new page on every visit”. It’s not obvious at work on a fast connection, but was apparent on a slower connection at home.
Here are two more links with good looking solutions I’m investigating.
1: http://www.fivesevensix.com/studies/ie6flicker/
2: http://wellstyled.com/css-nopreload-rollovers.html
January 6th, 2006 at 3:08 am
I have just put something similar on my website and i got rid of the flicker by going into my browser settings and not loading the page each visit if that makes sense, thanks
January 8th, 2006 at 7:59 pm
Erica – that indeed does make sense. I have heard that setting Internet Explorer (Windows) to “check for new page every visit” is something that many web page designers do. I think it’s used to stop IE reloading an outdated style sheet from the cache.
Firefox is nice here. You can simply use Ctrl+F5 or Ctrl+Shift+R to override the cache.
Bottom line – it’s mostly web designers who get this flickering. Any of the suggested methods will get rid of it. That’s assuming you don’t want to annoy web designers … ;-)
January 23rd, 2006 at 2:35 pm
I have used David’s suggestion of keeping all images (default, rollover, and on state) in one, and then just changing the position of the image in the css for my last two projects and it has worked beautifully with no flicker and no need for preload images.
Example can be seen here. (Note that this site is still in progress.)
February 1st, 2006 at 3:26 pm
Hi,
First of all, thank you for providing inspiration. Your enthusiasm is addictive.
Could you spare a few moments to explain David’s suggestion. I can’t quite get my head around it.
February 3rd, 2006 at 11:28 am
Explanation of David’s Suggestion:
Say you have 3 images, all 100 pixels by 40 pixels – one for normal, one for hover, and one for selected. Ok, instead of having 3 images and preloading them via javascript and changing them via css you just use one image, in this case it would be 300px by 40px with all three images laying side by side (say, in the order of above – normal, hover, on).
Now, in your css you just say something like the following to hide the text:
a#yourLink span {display:none;
}
or … if you want to be really accessible you could say:
a#yourLink span {position:absolute;
width:100px;
margin-left:-5000px;
}
Because display:none means it won’t be read by screen readers, but if you absolutely position it off the screen it will be hidden, but still “there”
Anyway, now you define your anchors using a window smaller than the actual image, in order to display just part of it. :
a#yourLink {display:block;
width:100px;
height:40px;
background image: url(yourImage.gif);
background-position: top left;
}
Now for the hover you can change the background position (indicated here by vertical and then horizontal values). You are basically telling the background image to be moved 100 pixels to the left so that the “second” image is revealed in your window:
a#yourLink:hover {background:position: -100px 0;
}
Now for the final “on” state:
a#yourLink.on {background-position:-200px 0;
}
Make sense?
April 24th, 2006 at 12:23 pm
[...]
Nav Bars on Steroids In Semantic and Gorgeous Navigation Bars I explained the method I use for creating [...]
May 3rd, 2006 at 2:54 pm
If you’re a fan of reducing the number of images used on a site, you can save lots of things bundled together in this manner. For instance, instead of creating separate image files for each button, just create one and shift it around as you describe. As long as you’re dealing with fixed dimensions it’s easy.
Heck, you can even attach background elements to each other depending on the specific uses.
December 1st, 2006 at 8:33 am
There’s no reason for using JavaScript to pre-load images even if you swap the backgrounds out (rather than move them, as you now do). Just use standard IMG tags and set visibility to hidden, or size them to be 1x1px and nestle them away, or whatever – I’m sure you get the idea.