Horizontal Subnav with CSS
Blog » CSS/XHTML » Horizontal Subnav with CSSHorizontal Subnav with CSS
Not too long ago I wrote a tutorial on how to create a drop down menu with CSS & jQuery, today I would like to go over how to create a simple navigation with a horizontal subnav.
In most cases we can achieve this effect purely with CSS, but since we have to attend to our red headed step child aka IE6, we will use a few lines of jQuery to cover all grounds.
Wireframe – HTML
Nest a set of links wrapped within the <span> tag, this is how the sub navigation will be positioned.
<ul id="topnav">
<li><a href="#">Link</a></li>
<li>
<a href="#">Link</a>
<!--Subnav Starts Here-->
<span>
<a href="#">Subnav Link</a> |
<a href="#">Subnav Link</a> |
<a href="#">Subnav Link</a>
</span>
<!--Subnav Ends Here-->
</li>
<li><a href="#">Link</a></li>
</ul>
Styling – CSS

Unlike a regular drop down menu where the subnav appears directly underneath the hovered/clicked list item, in this case all the subnav sets will start at the same location (left aligned – underneath the navigation).
ul#topnav {
margin: 0; padding: 0;
float: left;
width: 970px;
list-style: none;
position: relative; /*--Set relative positioning on the unordered list itself - not on the list item--*/
font-size: 1.2em;
background: url(topnav_stretch.gif) repeat-x;
}
ul#topnav li {
float: left;
margin: 0; padding: 0;
border-right: 1px solid #555; /*--Divider for each parent level links--*/
}
ul#topnav li a {
padding: 10px 15px;
display: block;
color: #f0f0f0;
text-decoration: none;
}
ul#topnav li:hover { background: #1376c9 url(topnav_active.gif) repeat-x; }
/*--Notice the hover color is on the list item itself, not on the link. This is so it can stay highlighted even when hovering over the subnav--*/
Now set the absolute positioning on the <span> tag 35px from the top. I added some rounded corners on the bottom for style (this will not work in IE).
ul#topnav li span {
float: left;
padding: 15px 0;
position: absolute;
left: 0; top:35px;
display: none; /*--Hide by default--*/
width: 970px;
background: #1376c9;
color: #fff;
/*--Bottom right rounded corner--*/
-moz-border-radius-bottomright: 5px;
-khtml-border-radius-bottomright: 5px;
-webkit-border-bottom-right-radius: 5px;
/*--Bottom left rounded corner--*/
-moz-border-radius-bottomleft: 5px;
-khtml-border-radius-bottomleft: 5px;
-webkit-border-bottom-left-radius: 5px;
}
ul#topnav li:hover span { display: block; } /*--Show subnav on hover--*/
ul#topnav li span a { display: inline; } /*--Since we declared a link style on the parent list link, we will correct it back to its original state--*/
ul#topnav li span a:hover {text-decoration: underline;}
For those who are not very familiar with how positioning works, check out the following tutorials:
- w3schools – CSS Positioning
- Absolute, Relative, Fixed Positioning: How Do They Differ?
- Stopping the CSS positioning panic
IE6 Fix – jQuery
Since IE6 does not understand li:hover (basically it only understands a hover event on a <a> tag), use jQuery to go around the issue.
For those who are not familiar with jQuery, do check out their site first and get an overview of how it works. I’ve shared a few tricks that I have picked up along the way, you can check those out as well.
Initial Step – Call the jQuery file
You can choose to download the file from the jQuery site, or you can use this one hosted on Google.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
The following script contains comments explaining which jQuery actions are being performed.
<script type="text/javascript"> $(document).ready(function() { $("ul#topnav li").hover(function() { //Hover over event on list item $(this).css({ 'background' : '#1376c9 url(topnav_active.gif) repeat-x'}); //Add background color and image on hovered list item $(this).find("span").show(); //Show the subnav } , function() { //on hover out... $(this).css({ 'background' : 'none'}); //Ditch the background $(this).find("span").hide(); //Hide the subnav }); }); </script>
Conclusion
Nice and simple! Hope this will come in handy in your future projects. If you have any questions, suggestions, or concerns, please don’t hesitate to let me know!
Similar Posts:
Tags: jQuery, navigation
This entry was posted on Monday, July 13th, 2009 at 11:32 pm and is filed under CSS/XHTML. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.







Why not use nested lists?
Thats really amazing. Thanks for the tutorial.
Nice tutorial, Soh. Menu looks very neat.
@Mariusz My first instinct was to use nested lists, but I thought this way would cut down on markup and was more simple
@janko , marufsiddiqui thanks fellas!
I recently discovered that :hover problem in IE6 and found another workaround. You can use a hover.htc bahaviour for IE6 only. I’ve found at least two different approaches when searching for it again. But I used this in http://www.sjaakpriester.nl/hover.html (it’s in Dutch – but you’ll get it, add extra li.hover class next to li:hover).
@Mariusz, @soh
By coincidence, I’m currently working on a horizontal sub-nav for my site based on nested lists (Joomla makes menus this way).
Positioning the subnav was tricky, especially for a relative beginner like myself, but I got it working somehow.
Instead of jQuery, some simple suckerfish would do the trick for IE6. Of course if you’re already using jQuery on your site then jQuery is fine too, but I wouldn’t install jQuery just to get IE6 hovers working.
@Soh
But it’s far less semantic and could cause annoyance later on if you want to change the navigation style.
It’s nice but I’d rather see it with nested lists
ooohh – i like it! clean, tidy and professional – top job!
Fantastic tutorial Soh! You make this sort of thing look so simple.
Thx, Soh, perfect as all the other things too: simple, straight and beautiful. But how would you implement a slight fallback solution if JS is turned off?
I’ve found an interesting article about sprites (http://www.alistapart.com/articles/sprites2) from alistapart. But they used a fixed set of images for there menu structure. But it still works w/out JS.
Do you see a chance to combine both techniques?
Had one question, but with a little testing on my end, I figured out my own answer!
Something else I noticed, though, is once you activate the hover state on a menu item, if you don’t move the mouse fast enough, the sub nav disappears before you get to it. Any comments/fixes?
Otherwise, nice work.
Hey, you guys that freely share your time and knowledge CANNOT BE THANKED ENOUGH! Love the presentation of your tutorials… especially the CSS being bundled directly in the HTML file.
I’m a LONGTIME hand coder… extra kudos to a guy that COMMENTS his code!!!
Thanks again for your time, effort, and GENEROSITY!
@deef & Lloyd Vincent – Thanks for the other suggestions! I will def look into them
@Ryan Roberts I agree in that sense, I guess there was a good reason my instinct was poking at me when I created this hehe thanks for your good suggestion~
@fritzek this would work in pretty much all browsers except IE6 and below. No js is needed~
@Mike it may be that you hovered out of the list item which caused it to hide again. There isn’t much that I can think of other than making the hover area larger so people can’t skip outside of it~
@all who commented, made suggestions: thank you
Awesome. I love the simplicity of this. Especially compared to nested lists.
I think it’s much better to create drop-down menus using only CSS and (X)HTML. Like here for example http://www.cssplay.co.uk/menus/drop_examples.html
An afterwards — use jQuery for all fancy shading and sliding.
As a result — you get «Working without js-on menu» and nice menu for peple with js-on.
@Dmitry The only js used on this subnav is for IE6
Maybe I should switch my Title since its maybe misleading
Thanks for the link they have a lot of sweet examples there!! Bookmakred
Hi, i’ve done it with just CSS (no IE6 support) on http://www.klap.com
I understand that the js is solely for stupid browsers (again IE6) support, but should we support that?
Please respect semantic coding first, use double nested s. Nevertheless you provide good example of graceful degradation coding.
i mean: *use double nested uls*
If you wanted to stick with the use of a span (although I tend to agree that nested lists is probably the best way to go about this) you could actually surround the entire list-item content (not the list item itself) with an anchor tag and apply your hover styles to it.
As your spans and links are all inline this will validate well. The only thing you’ll have to do is give the surrounding link an href value of javascript:; (or your favorite “link that won’t do anything when clicked” href value) to avoid any behavioral wierdness that comes from nesting links in links.
The above was in regards to removing jquery completely and still having IE6 support.
Thanks for the tutorial, but I was wondering as I’m not the best jQuery guy – can you do some fading effect to it?
Great tuts…
I used it on my site now, thank you.
nice tut, but
“nested lists”+1
Awesome Tutorial! I think ill use this for the alternate theme I’m Developing for v3 of my site
Thank you for sharing!more:http://www.open-open.com/ajax/Menu.htm
This is a great jquery tutorial. I have added it to http://tutlist.com
nice tutorial … as u mentioned earlier u work this for joomla.. so have you made any component or module for this menu ? if so pls i need it …
Is it possible to make that SPAN shows when the link is clicked? (active)?
Thank you!
GOOD JOB.
@Brian Jørgensen Yes you can, check out this tut on how to make it fade in/fade out: http://jqueryfordesigners.com/broken-repeating-animations/ also check out the link below.
@EternalThug if you want it to appear using a click method, you can change the hover to click.
Both of you guys can check out the demo here (its a combination of what both of you were asking for. So try to experiment with it :
http://www.sohtanaka.com/web-design/examples/horizontal-subnav/index2.htm
Thanks for this article, how can we use this one for wordpress category and subcategory
Hey, i love this tutorial, thanks.
Nice work!
Can you please help me in accomplishing the following:
I need to be selected the Main Menu “About” & the sub menu item “The Team”. How can I do this ?
My aaim is to when someone open the page “the_team.php”, then both the About and The Team will be active..
And one more requirement, while moving on other items, show their sub items like current menu.. But after the navigation, the About & The Team will get to be activated.. Is this possible ?
Sorry for the above comment!Love this tutorial!! Thank you!
I have another question. Is there a way that when a visitor clicks a sub navigation link, the sub navigation links remain in place and do not fade away? This will provide the visitor more options under than main category to click on. However, if they hovered over another main nav link..(the top level), then the sub navigation would fade away and be replaced by that new sub-navigation. I hope I was clear on that. Your help would be greatly appreciated. Thanks again!
Hey Soh, the problem with your example from
http://www.sohtanaka.com/web-design/examples/horizontal-subnav/index2.htm
is that it doesn’t work well with Javascript turned off. Maybe have some sort of css backup when the user rolls over it, it will be given the “display: block” CSS property. I’ll look into this for you!
Hi I am using a similar technique for my nav but cant figure out how to keep the sub-nav visible once that sub is active. Can anyone help with this?
Sorry, didnt read previous comments, seems like the question has been asked.
@Joseph.A / bp+
To make a nav have its active state, you will need to associate a body ID (in your case body id =”team” ) and match it with its current list item link class (<a href="#" class="team">The Team</a>). your css would look something like : #team ul#topnav li span a.team {color:red;}
If you want it to be visible by default, you should approach this similar to the tabbing function found in this tutorial: http://www.sohtanaka.com/web-design/simple-tabs-w-css-jquery/
@Nintensity
All you have to do then is to add the following:
Good point!
ul#topnav li:hover span {display: block;}
Thanks~
Hi Soh,
It works..thank you for your quick response. nice tutorials..
If this comment section has a subscribe feature, that will be good.
wow! Awesome!
Hi!
First of all thank you very much for your tutorial, I’ve been looking for something similar for weeks :-S
Although I tried to more or less copy your work with some design adaptations, I can’t manage to make it run in IE8, nor in IE6.
It’s on http://test.pfarreimusik.ch
What am I doing wrong?
Thanks for your support!
buemplizer
Thanks for the article, I will be using this soon.
Hi I’m a second year student and we have a project to do. A website to be made in dreamweaver.. can i put this codes there in css section??
Thanks
Thank you so much for sharing your knowledge, this is just the kind of menu I am after!
Thanks for a nice article
awesome stuff!! I want to be able to remove the hover out event so the horizontal sublinks always stay put till you hover over the next main link. I’ve been messing with it myself with not much luck. Any suggestions?
As usually thanks for great tutorial, I will probably use it sooner or later
Great tuts !
But I have two questions :
- how can I have the “subnav” remain for a few seconds after the mouse has left its spot ?
- I would also like to have the “subnav” appear when the page of the corresponding nav is loaded. I tried the homemade code below with no success :
$(document).ready(function() {
$(”span.open_at_load”).show();
}
with added in the html code.
Thanks a lot for your help !
Awesome code, thank you for sharing. I do however have the same request that Jay has above – the need to change the hover out property on the sub navs – so that they stay displayed on hover-out or until another menu item is hovered on. I was hoping it was as easy as deleting “$(this).find(”span”).hide();” but that doesn’t exactly work
Thanks for sharing your code again and please help!
Great tutorial, I’m working to implement it on a design for a current client. It works perfectly!
All the best.
@Will_Powered
This is great. I would also like to know how to have the subnav appear when the page of the corresponding nav is loaded and have it fade when you hover over another link and that links subnav appear.
Thanks!
good menu and similar to the one I’d hacked out myself…but I’ve got a client request that is pretty weird. They want the subnav to appear on hover, but also STAY when the user clicks on one of the nav items in the top nav. So, work this way on hover, and another way when the user clicks. I can’t for the life of me figure this out. any ideas?
Thanks! Added to my design favourites!
Personnally I would use nested lists, wouldn’t that help a tiny bit in SEO?
Hello, very interesting example.
I wonder if there is a way to insert a second (vertical) submenu, a menu from the subnav.
example, a list of members that appears below the “team” in “about”.
thanks mate, this is a great tut. thanks for sharing … anyway
.
hm… I don’t but people blinds can use it easy?
I like. How would you make it vertical?
nice beautiful work ! i have added it in my favorites.
could you also give some referenct to learn the JQuery.
Thanks,
Use the jquery hoverIntent plugin to avoid the annoying issue of the hover being cancelled if you move the mouse too slowly or accidentally roll off of the hover trigger.
Also, you *really* should use nested ul’s for this.
To the previous suggestion of nesting the secondary ul’s *inside* of the anchor.. you can’t do that. It won’t validate and will almost surely cause problems in many browsers. Links shoudn’t contain block level markup and should *never* contain another link within it.
Não entendi nada.
Nada!
Great tutorial man. Thanks a lot !
awesome tutorial thank you.
Amazing,
i love your menu and i want to add this in to my templates,
So what license its?
thanks
Abba Bryant – how did you implement the jquery hoverIntent plugin?
Thanks a lot for this post. I really like your site. You make use of a lot of great css and javascript tools.
Thanks for the tutorial. I like your sites design too. Ive just realized after reading through your comments that I can probably find a nested list solution for my horizontal subnav in wordpress, but if anyone is interested, I wrote a little jquery to convert nested lists (wordpress pumps out with wp_list_pages) into the span type list you have used.
http://www.pastie.org/630365
really awesome thanks for sharing. M
I second Wallaces’ question. Anyone know a way to place a third level vertical menu triggered from the sub level span links? that would be awesome.
[wallace
Hello, very interesting example.
I wonder if there is a way to insert a second (vertical) submenu, a menu from the subnav.
example, a list of members that appears below the “team” in “about”.]
i think, well done
thx a lot for publishing!
I love the tuts on this site. Very helpful, bookmarked
I am also trying to find out how I can have the submenu stay active.
I read all the comments and your suggestions, particularly this comment of yours:
[quote]@Joseph.A / bp+
To make a nav have its active state, you will need to associate a body ID (in your case body id =”team” ) and match it with its current list item link class (The Team). your css would look something like : #team ul#topnav li span a.team {color:red;}
If you want it to be visible by default, you should approach this similar to the tabbing function found in this tutorial: http://www.sohtanaka.com/web-design/simple-tabs-w-css-jquery/
[/quote]
The problem I have is that when I click on a submenu, let’s say “Team”, and go to the actual “team.html” page with a , I can make it active as you proposed with this code: #team ul#topnav li span a.team {color:red;} BUT I have to hover over it on order for it to appear. I want to have the submenu active with the actual “team” button active as well.
I read your “Tabs” tutorial, and don’t understand how I can adapt the code to make it work when it actually navigates away from the main page to another html page, vs. just switching back and forth between the tabs.
Don’t know if this makes sense, so here is a link to a screenshot of my desired navigation:
http://img97.imageshack.us/img97/9771/navit.png
it seems to be a combination of CSS sprites for the main navigation, and of the other two tutorials of yours for the rest…
help appreciated: salvia{at}gmx{dot}li