You are looking at archived content. The hot new stuff is happening at Veerle's blog 3.0. You should check it out!

Mar 28

2 level horizontal navigation in CSS with images

2005 at 11.49 pm posted by Veerle Pieters

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?

Another 2 level horizontal navigation in CSS

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>
     <li id="softw" title="link to software"><a href="#">Software</a></li>
     <li id="hardw" title="link to hardware"><a href="#">Hardware</a></li>

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.




permalink this comment lazymouse Tue Mar 29, 2005 at 12.42 am


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!




permalink this comment Pilok Tue Mar 29, 2005 at 01.14 am


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. ;-)



permalink this comment Veerle Tue Mar 29, 2005 at 01.49 am

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.



permalink this comment ephi Tue Mar 29, 2005 at 02.20 am

Dear Verlee, I checked this menu with IE 6 and it work, even though I notice no JavaScript around. Good job!



permalink this comment Gianni Tue Mar 29, 2005 at 03.56 am

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?




permalink this comment Aleksandar Tue Mar 29, 2005 at 06.57 am

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 {

It does not work in IE, but it does not hurt it either.



permalink this comment Veerle Tue Mar 29, 2005 at 07.28 am

@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.



permalink this comment Erik A. Drabløs Tue Mar 29, 2005 at 08.29 am

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.



permalink this comment Dustin Diaz Tue Mar 29, 2005 at 09.23 am

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



permalink this comment Matt Harris Tue Mar 29, 2005 at 09.58 am

Veerle, you are a wealth of incredibly useful knowledge and tutorials.  I check your web site daily.



permalink this comment Dustin Diaz Tue Mar 29, 2005 at 10.18 am

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.



permalink this comment Veerle Tue Mar 29, 2005 at 10.26 am

@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 ;-)



permalink this comment Ollila Tue Mar 29, 2005 at 11.43 am

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.



permalink this comment Dustin Diaz Tue Mar 29, 2005 at 02.44 pm

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 :)



permalink this comment Daynah Tue Mar 29, 2005 at 02.57 pm

wow Veerle, this is beautiful. :)  Good work!



permalink this comment Ken Tue Mar 29, 2005 at 04.20 pm

VERY nice. one of the best horizontal menus i’ve came across yet. definitely bookmarked.



permalink this comment Arthur Bahadourian Tue Mar 29, 2005 at 05.44 pm

Thankx for the opportunity!

My poor attempt of similar navigation.

Please be gentle…it’s still work in progress.



permalink this comment Zeerus Wed Mar 30, 2005 at 08.07 am

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.



permalink this comment Dustin Diaz Wed Mar 30, 2005 at 01.44 pm

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!!



permalink this comment willem Wed Mar 30, 2005 at 02.39 pm

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



permalink this comment bruce Wed Mar 30, 2005 at 11.56 pm

Wow this is nice!!

thanks so much for this!!



permalink this comment Vitaly Friedman Thu Mar 31, 2005 at 12.08 am

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,



permalink this comment Veerle Thu Mar 31, 2005 at 12.52 am

@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 :-)



permalink this comment Katie Dixon Thu Mar 31, 2005 at 02.46 am

Excellent article, I’m looking forward to trying this out soon. Thanks so much!



permalink this comment jasmanac Thu Mar 31, 2005 at 06.22 am

Looks OK but still don’t work in Opera 7 ...



permalink this comment Zeerus Thu Mar 31, 2005 at 06.50 am

@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.



permalink this comment Dustin Diaz Thu Mar 31, 2005 at 12.35 pm

@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 ;)



permalink this comment Ezku Thu Mar 31, 2005 at 02.10 pm

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 :)



permalink this comment Zeerus Fri Apr 1, 2005 at 06.17 am

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.



permalink this comment Zeerus Fri Apr 1, 2005 at 09.02 am

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”>

so you’ll be importing it twice, hopefully disabling the flash



permalink this comment Michael Fri Apr 1, 2005 at 09.11 am

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. :-)



permalink this comment Zeerus Fri Apr 1, 2005 at 09.27 am

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.



permalink this comment George Fri Apr 1, 2005 at 10.16 pm

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.



permalink this comment Veerle Fri Apr 1, 2005 at 11.55 pm

@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 ;-)



permalink this comment Eric Shepherd Sat Apr 2, 2005 at 05.45 pm

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.



permalink this comment George Mon Apr 18, 2005 at 03.47 pm

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.



permalink this comment Brimmy Tue May 3, 2005 at 01.39 pm

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;


Great looking menu!



permalink this comment xRay Tue May 10, 2005 at 02.05 pm

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!




permalink this comment Mike Tue May 10, 2005 at 06.36 pm


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

Thanks again Veerle!



permalink this comment Veerle Wed May 11, 2005 at 02.31 am

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).



permalink this comment Tikketim Wed Jun 1, 2005 at 03.45 am

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

That tutorial explains you how to solve it.



permalink this comment janice Mon Jul 18, 2005 at 10.16 am

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.



permalink this comment lex Thu Nov 10, 2005 at 07.05 am

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.


btw excellent website. i like it very much



permalink this comment Veerle Fri Nov 11, 2005 at 04.16 am

@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.



permalink this comment lex Fri Nov 11, 2005 at 06.48 am

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.



permalink this comment Gerrit Tue Nov 22, 2005 at 07.45 am

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!



permalink this comment Gilbert sévigny Wed Nov 30, 2005 at 09.16 am

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!




permalink this comment Veerle Thu Dec 15, 2005 at 08.27 am

@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! :-)



permalink this comment bassek Fri Mar 31, 2006 at 09.00 am

great piece of code, thanks for your explanation, which is such as cool as this blog.



permalink this comment jeff rainey Wed Apr 12, 2006 at 02.23 pm

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.



permalink this comment Adnan Oner Fri Apr 14, 2006 at 02.07 pm

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



permalink this comment Adnan Oner Sun Apr 16, 2006 at 07.22 am

never mind, I just made 2 navlists and now it works like a charm



permalink this comment Custom Web Development Sat Jul 8, 2006 at 03.08 am

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.

Commenting is not available in this weblog entry.


buy something from my Amazon wishlist