Mar 28
2 level horizontal navigation in CSS with images
2005 at 11.49 pm posted by Veerle
A 2 level horizontal menu is not that difficult to create using CSS. If you keep it all text-based it should be doable once you know the basics. But how about the creation of such menu using images only for the purpose of having the extra graphical freedom?

The structural code doesn't contain any images. For every button we use a different id. These id's are then styled. The text will be replaced by images, used as a background. Here is an excerpt of the code:
<ul id="navigation">
<li id="home" title="link to homepage"><a href="#" >Home</a></li>
<li id="products" title="link to products"><a href="#">Products</a>
<ul>
<li id="softw" title="link to software"><a href="#">Software</a></li>
<li id="hardw" title="link to hardware"><a href="#">Hardware</a></li>
</ul>
...
The trick is using "text-indent: -9999px" (this places the text outside the browser window) and use one image (the entire navigation) as a background.
The navigation of the first level contains two images (navigation.gif and navigation_over.gif). For some reason, my rollover effect didn't work using only one image, it does work however in the second level. Since it works in the second level I have no idea why it doesn't in the first one :-S
ul#navigation li a {
border: 0;
display: block;
height: 25px;
background: url(navigation.gif) no-repeat;
}
ul#navigation li a:hover {
border: 0;
display: block;
background-image: url(navigation_over.gif);
}
By using background positioning, width, height and "display:block" we 'reveal' each button of the navigation. Here is an example of the support button:
li#support a {
width: 67px;
}
li#support a:link,
li#support a:visited,
li#support a:hover {
background-position: -264px 0px;
}
What I wanted is that when you roll over the submenu that the image of the first level is still in the rollover state. I have no idea if this is possible, but I think it is, only have no idea how. If anyone has suggestion please don't hesitate to share, thanks.
53served
1
Veerle;
I’ve been looking for a horizontal menu in CSS for ages. I found a few ways, but this one looks like the best for my needs.
I’ll be trying this later .... thanks for the tutorial, Veerle; you won’t believe how much more productive I’ve been since following your earlier tutorial on CSS.
All my sites are now CSS, not a table in sight, and it’s all thanks to you, Veerle.
Thank You!
Steve
lazymouse
2
Hi,
this a very clean menu but I have several remarks:
- Why didn’t you use gif backgrounds instead of complete image menu? if you look carefully at the images when a rollover occurs, you will see a small move of the image. And if you do so, you do not need mutliple styles anymore for the different button (#home #products ...).
- To keep the first level menu “on” while rolling over the sub-menu, i woul use Javascript to detect the rollover on the second level menu and changing the style of the first level menu. Just look at Suckerfish javascript menu or similar.
CSS is not a exact science, everybody can have a personal approach to achieve the same goals. ;-)
3
Hi lazymouse, that’s great to hear, thanks for letting me know :-)
Hi Pilok, I have double checked again but I see no moving, I’ve used the Xscope zoom tool, this way I’m 100% sure. To answer on why I use 1 image that’s because once this image is loaded, it’s all loaded and there are no ‘empty’ moments or ‘gaps’ once you rollover an image (which happens if you use separate ones, since it has to load on the moment you roll over). This technique is called the Navigation Matrix. Thanks for the javascript tip, but I was wondering if it was possible with pure CSS.
4
Dear Verlee, I checked this menu with IE 6 and it work, even though I notice no JavaScript around. Good job!
5
Hi Veerle,
why are you using “text-indent: -9999px” and not something like this?
<li><span style="hide">menu entry</span></li>
#navigation span.hide { display: none; }
Do you think this could work?
Bye,
6
Graphics are hard to read but nice. I have done the same thing, only with text and would not call it that easy - it requires way more knowledge than just basics.
The answer to your last question:
li:hover > a {background…
}
It does not work in IE, but it does not hurt it either.
7
@Gianni, it’s better not to touch the structural code (if it’s possible) by adding spans and classes etc. If I can avoid these, then I do. Not sure if this would work either, since it will probably hide the background images as well. I only use display: none for the submenus since they should be hidden.
@Aleksandar, yes you are right it isn’t easy, I must have mentioned 1 level, since 1 level is doable, 2 is another case you are right ;-) Great example you have there. Thanks for sharing this and for the :hover tip. I’ll certainly check this out.
8
As usual, a really nice tutorial and example example. Unfortunately it doesn’t work in IE5.x/Win. The level two links don’t show up at all. Which means I won’t be using it for my own pages in quite some time yet, as my school is still stuck in 1999(?) which is where I get about 6% of my pageviews from.
9
I’m not under standing… why is everyone saying that there is no javascript?
It’s right here.
Veerle, this is very cool, but I don’t see how it’s much different than the ala suckerfish drop downs… and you don’t even need the unique id’s
10
Veerle, you are a wealth of incredibly useful knowledge and tutorials. I check your web site daily.
11
and just so I don’t sound like a big meanie, compliments to the css chef. I still like the imagery used in the menu itself. Good job.
12
@Erik A. Drablos, I didn’t test in IE 5, I was already sure that this would be ‘undoable’, IE is already a bit of trouble so ... If I know the site needs to work in IE 5 I don’t even bother it would be javascript based, no doubt.
@Dustin, OK the .htc behavior script is there, but it’s for IE (6) only. It works perfectly in Netscape, FireFox or Safari without this script. It’s just there because IE doesn’t understand :hover which is needed for the submenu (second level) to work. Also I’m not sure how it would work without these id’s… The suckerfish menu (providing me with a url would have been handy btw, I had to look it up) is text based not image based, at least not every button has a different background. The suckerfish menu uses 1 and the same background for each button, in my example all buttons have different backgrounds (in fact different x and y coordinates and widths).
@Matt I try to do my best ;-)
13
Nice job Veerle. Your tutorials are always tight and easy to understand. Malarky has come up with a new method of IR called MIR. Check it out. Takes care of those pesky horizontal scroll bars in suspect browsers caused by the text-indent: -9999px. Once again very nice job.
14
right right. i think the suckerfish does the same thing where it adds in the extra snippet:
if ( document.all[] )
{
// process ie
}
So really, yea, for the ideal browser, this would be a pure css menu. Luckily enough, the rumors say that IE7 will be implementing :hover on all elements :)
15
wow Veerle, this is beautiful. :) Good work!
16
VERY nice. one of the best horizontal menus i’ve came across yet. definitely bookmarked.
17
Thankx for the opportunity!
My poor attempt of similar navigation.
Please be gentle...it’s still work in progress.
18
What a great tutorial. I don’t have a use for it yet, but I’m sure I can incorporate it in a downloadable template on my website. I like the color scheme of it. It hapenns to match the theme of a website I’m working on.
19
Wow, I know this is my third post on this…
but what timing!
Did anyone else see ALA’s Hybrid which shows something very similar!!
20
well, that’s just amazing....
I was looking for a menu just like this, and now all the sudden there are two (ala just mentioned) solutions.
great tutorial, I realy like your articles on CSS
21
Wow this is nice!!
thanks so much for this!!
22
Veerle, thanks for a great work!
Still I’d like to inform you about a bug in Opera. The menu is interpreted this way in Opera 7.50.
With best regards, Vitaly Friedman,
http://www.alvit.de/vf/
23
@Ollila, thanks for the tip, this looks very interesting. I’ll certainly check it out and experiment with this :-)
@Arthur Bahadourian, nice work!
@willem, the ALA article is just perfect! I’ll see if I can adjust mine to the technique Eric Shepherd is suggesting.
@Vitaly Friedman, I was a bit afraid it wouldn’t look ‘pretty’ in Opera :-S
Seems like I have to do some work to get it perfect, but when I do I’ll sure let you all know.
Thanks for all the great tips and comments folks :-)
24
Excellent article, I’m looking forward to trying this out soon. Thanks so much!
25
Looks OK but still don’t work in Opera 7 ...
26
@Dustin: yeah, I had seen that article yesterday a few minutes before I came to this. my browsing starts with Stopdesign, then ALA, then I make my way over here. And if I’m not too busy I try to visit my website. Only about 770 members more and I’ll be as big as this blog.
27
@veerle @willem, the ALA article is just perfect! I’ll see if I can adjust mine to the technique Eric Shepherd is suggesting.
what the heck, I’m the one that referenced ala :p ;)
28
Nice work, Veerle, as always.Works perfect with Opera 8b3.
Ollila already mentioned this, but I’d recommend everyone to take a look at MIR. It’s rather elegant a hax :)
29
I’ll test it later today in Netscape 8 beta. It probably won’t work, then again, the quality of netscape is always falling. The beta was super slow, but it had a lot of great features. I should try it on XP and Panther to see how the speed matches up.
Nevermind, I tested it, it looks wierd. Everything is alligned differently, but it could just be me. Anyone else have a different view. I changed around the -9999px thing, and it fixed it a little bit.
30
I just realised something else wrong with the menu. When it first loads up, the menu quickly flashes orange, it only lasts for about a second, but makes a difference.
The only thing I can think of is to adapt BlueRobot’s FOUC method to your own workings, and instead of using it to disable a flash of unstyle content, use it to automatically load the default colors and images. So load the stylesheet in the <link rel> tag, and again using
<style type="text/css">
@import
</style>
so you’ll be importing it twice, hopefully disabling the flash
31
Great job of the navigation tutorial, many thanks on your efforts. But, may I ask what font you are using for the navigation?
Thansk again. :-)
32
Another thing, to use less images, you could try turning the text in the LI elements into H6 elements, then use MIR. This will eliminate the use for the long image, because the MIR would rpelace the text, as long as it’s a headline, with a PHP generated image. I will try this to see if it works. I don’t think it will, because with the images, you already have the text where you want it to show up. With MIR you would have to mess around with the positioning.
Just thought you might want to take this into consideration for a follow up to this article.
33
Seems like more code that its worth. How many lines do you have just for the menu alone? not to mention the addition of the .htc.
Also using span to hide your text is probably better than making it draw it way over on your neighbors screen. The whole purpose of css is to lighten the load, make things more accessible, and leaner.
While this menu is beautiful I think you could nearly have styled a whole site with all that css instead.
Also I checked it in IE mac, the worst browser in the world, and the hovers dont work.
By the way it does look great.
34
@Michael, I’ve used “standard_07_57” you can buy this font here.
@George, “While this menu is beautiful I think you could nearly have styled a whole site with all that css instead.”
Really? I challenge you :-) Maybe we can all learn from it. A site with such a small amount of CSS is impossible even for a regular blog it will be more.
Also it is an experiment (not a ‘real’ example), just to show what is possible with images instead of text (like most CSS menus). I personally rather use something like this instead of an old-school seperate gif tabel menu. A little creativity doesn’t hurt ;-)
35
That’s not really a lot of CSS, and CSS is text, and it only loads once for the entire site. It’s a pretty lightweight menu, overall.
It looks good, and I like the subnav popping out just under the associated upper level nav; of course, this is a problem if there are lots of options...my next project will be a method to arrange the subnav differently depending on whether it is long or short, centering it if it’s too long.
36
Dont get me wrong, it looks great. but over two hundred lines of code for the navigation? I’m coding a site now that is at 500 lines not including print.css. the navigation alone is only @ 45 lines. the method just seems excessive. beautiful, but excessive.
the whole point of css (to me) is to lighten the load even if only by a few kbs.
37
Hello Veerle
I was just wonder how you came up with the correct positions for the “margin-left: 37px;” for each sub menu.
I cannot seem to get the my submenu to align correctly.
/*<group=level 2>*/
#navigation li ul {
display: block;
visibility: hidden;
position: absolute;
left: 0px;
width: 300px;
margin: 0;
}
#navigation li:hover ul {
visibility: visible;
z-index: 100;
}
#navigation li#extra ul {
background: none;
height: 21px;
margin-left: 191px;
}
#navigation li#products ul {
background: none;
height: 21px;
margin-left: 37px;
}
* html #navigation li#extra ul {
margin-left: 233px;
}
* html #navigation li#products ul {
margin-left: 79px;
}
/*</group>*/
Great looking menu!
38
Looks like this could replace a menu I currently have which uses Javascript and gives me security messages on Windows IE6.
Does this mean that menus with css are the way around these security messages?
Thanks Veerle!
Ray
39
Veerle,
Your example has helped me sooo much! I ran into some issues with the css hybrid menu Eric Shepard made on A List Apart. Thankfully I found yours! Great tutorial. I used this menu for a school project. You can check it out at
www.therochesterperspective.com
Thanks again Veerle!
40
Hi xRay, well there is one script. It’s a behavior script that is linked in the CSS. Only IE needs this script since it doesn’t support :hover which is needed to make the second level work. This script can be found here (don’t forgert to choose : view source code because the page will be blanc).
41
Nice tutorial Veerle but you forgot something : the ‘flicker’ bug in IE 5.0. When u have a hover on an image , the image will flicker in IE 5.0
http://www.webreference.com/programming/css_flicker/
That tutorial explains you how to solve it.
42
that’s a great tutorial.
would this work for a vertical menu?
i’ve been playing around with it but haven’t as yet got it to work.
43
Hi Veerle!
a question!
is it possible with this menu to ‘freeze’ the submenu when you click on one item?
i need a similar navigation, but to make a workflow more visible a need to freeze the submenu and let it stick to the menu until i am finished with all the menu items in it.
can this be solved with css or does it require php or javascripts?
just wondering if someone could point me in the right direction.
thanks
Lex
btw excellent website. i like it very much
44
@lex, I haven’t found a way to accomplish this (mostly because of lack of time to look into this). Maybe this URL might help you out or give you some ideas. There are some very neat multileveled menu examples here. Check out the Netymology with horizontal submenus.
45
hi veerle,
thank you for this url. i will look into this, but it looks like something i could really use.
thanks again. also for your quick respons.
46
Hi Veerle,
Thanks for this tutorial - it was just what I needed!
I have been playing around with it and made some improvements:
- I got it working with one image for the main menu.
- I simplified the positioning of the submenu items.
- I use a transparent 1 x 1 gif for the <a href> in the html instead of the text-indent. This shows the menu item names when images are turned off.
It’s here.
I tested it in Opera 8.5, Netscape 7.1, Firefox 1.07 and IE 6 - works like a charm!
Thanks again for this tutorial!
47
We’ve found a solution to your “two images in navigation” problem…
just use ::
ul#navigation li a:hover {
border: 0;
display: block;
background-position-y: -25px;
/*background-image: url(navigation_over.gif);*/
}
and for every li
ex.: li#products a:link,
li#products a:visited,
li#products a:hover {
background-position-x: -52px;
}
By doing this you shift the backgroud for all li rollover to -25px in y-axis and keep only the x-axis shift for each particular menu item.
Good work!
A+
48
@Gilbert, sorry for my very late reaction here. I still need to look at your code more in detail. Thanks a bunch for doing the effort to post this here. This is very useful information to learn from. Super! :-)
49
great piece of code, thanks for your explanation, which is such as cool as this blog.
greetings
bassek
50
Thanks for a great menu. I have been looking for an images based tiered horz. menu that used images. Even gets around that nasty IE flicker problem. Good job.
51
Hi veerle, the menu is great… but I have a problem. I want to make 2 ‘lines’ of navigation, without making 2 navlist (or is this impossible?). Any idea’s?
Keep up the good work, Adnan
52
never mind, I just made 2 navlists and now it works like a charm
53
How i can add a background image to my links on the top of my div, for example my link dive is of 100*100 and when you roll over mouse on link there should be an image displayed on the top of that div.
thanks much.
dizyn