Menus play an essential part on the web. They allow users to find their bearings and help them navigate your website. When designing menus, usability is the key.
Beginners often struggle with the basics. In this tutorial I'm going to show you how to create a simple, usable and functional horizontal menu with HTML and CSS. I will also dive a little bit into jQuery to add animations to your menu.
![]()
This tutorial assumes you have a basic knowledge of HTML and CSS. It’s recommended to use a CSS reset for consistency. I use the one by HTML5Doctor.
The Basics
Let's start with the basic HTML structure of the menu:
<ul id="coolMenu"> <li><a href="#">Lorem</a></li> <li><a href="#">Mauricii</a></li> <li><a href="#">Periher</a></li> <li><a href="#">Tyrio</a></li> <li><a href="#">Quicumque</a></li> </ul>
A menu consists of an unordered list, and each list item contains a link with the text. Don’t create unnecessary divs. You don’t need any.
To add a sub menu simply nest another unordered list inside the item that's going to have the sub menu, like this:
<ul id="coolMenu">
<li><a href="#">Lorem</a></li>
<li><a href="#">Mauricii</a></li>
<li>
<a href="#">Periher</a>
<ul>
<li><a href="#">Hellenico</a></li>
<li><a href="#">Genere</a></li>
<li><a href="#">Indulgentia</a></li>
</ul>
</li>
<li><a href="#">Tyrio</a></li>
<li><a href="#">Quicumque</a></li>
</ul>
As you can see, creating the structure is very simple. This is how it should look in your browser at this stage:
![]()
There are multiple ways to set up the CSS for a horizontal menu. After many years I found that this is the quickest and cleanest way to do it:
#coolMenu,
#coolMenu ul {
list-style: none;
}
#coolMenu {
float: left;
}
#coolMenu > li {
float: left;
}
#coolMenu li a {
display: block;
height: 2em;
line-height: 2em;
padding: 0 1.5em;
text-decoration: none;
}
#coolMenu ul {
position: absolute;
display: none;
z-index: 999;
}
#coolMenu ul li a {
width: 80px;
}
#coolMenu li:hover ul {
display: block;
}
- I decided to float the whole menu to contain it but you can use overflow hidden or even set a fixed width for the same purpose.
- It is important to float the list elements rather than the links.
- The links should be displayed as blocks, otherwise, they won’t behave as expected.
- Absolute position the submenu and hide it to remove it from the regular flow and make it invisible. Also, set a high
z-indexto prevent the submenu from showing behind other elements. - Set a height for the link elements and the line-height equal to the height to center the text vertically. By specifying a fixed height instead of just using padding you avoid flickering problems with jQuery animations later on.
- Even though it’s not necessary to set a fixed width for the submenu items, it’s always a good practice. It allows you to style them more consistently later on.
- Notice that the hover state is set on the list element and not the link.
With all this set, the menu should be already working. Try opening it in your browser and hovering over the third option to show the sub menu.
![]()
Improving Usability
This step will cover how to style the menu with some basic CSS to make it more accessible.
/* Main menu
------------------------------------------*/
#coolMenu {
font-family: Arial;
font-size: 12px;
background: #2f8be8;
}
#coolMenu > li > a {
color: #fff;
font-weight: bold;
}
#coolMenu > li:hover > a {
background: #f09d28;
color: #000;
}
/* Submenu
------------------------------------------*/
#coolMenu ul {
background: #f09d28;
}
#coolMenu ul li a {
color: #000;
}
#coolMenu ul li:hover a {
background: #ffc97c;
}
Keep in mind this is very basic, and is meant to be just an example. You can style this however you want. The important thing to remember here is, as I mentioned before that the hover states, are styled in the list items and not the links.
This is how the menu looks so far:
![]()
Adding Animations
This final step is not necessary but it’ll help you add animations to your menu with simple jQuery. The first thing you need to do, of course, is to call the latest jQuery plugin on your website:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
Now, let’s add a "noJS" class to the submenu to be able to unhook the hover css state in jQuery. This will also ensure that the menu will still work when javascript is disabled.
<li>
<a href="#">Periher</a>
<ul class="noJS">
<li><a href="#">Hellenico</a></li>
<li><a href="#">Genere</a></li>
<li><a href="#">Indulgentia</a></li>
</ul>
</li>
You also need to add the class to the sub menu CSS hover state:
#coolMenu li:hover ul.noJS {
display: block;
}
Now that everything is set let’s add some magic:
$(function(){
$('#coolMenu').find('> li').hover(function(){
$(this).find('ul')
.removeClass('noJS')
.stop(true, true).slideToggle('fast');
});
});
The code is pretty explanatory. The script finds the immediate children list items and adds a hover function. Inside the function it removes the "noJS" class since we’re using JavaScript, and then it tells the menu to slide down on hover and to slide up on un-hover. This is achieved with the slideToggle function. The stop function prevents the animation from repeating itself if we hover multiple times.
Further Notes
The menu should work in IE7+ and all other modern browsers. I didn’t bother to support IE6. I’m sure it could work with some fixes here and there but that’s not the purpose of this tutorial.
I encourage you to try some CSS3 properties to style your menu, the possibilities are almost endless. I suggest you use the Colorzilla gradient generator to create your gradients.
I look forward to see what you can do.
Navigation menus are the most important element one should pay attention when designing a website. Web-developers can create user-friendly horizontal or vertical navigation menus using CSS. Javascript makes it possible to create more interactive, more responsive and more flexible navigation to any website.
By using css transitions you could achieve that scrolling effect as well. No 31,31 KB jquery-include needed
Of course you can, but with jQuery it'll also work on browsers that don't support css transitions.
When I tried the example, the submenu is showing to the right underneath the main menu item. I'm new to css so I'm not sure where and how to fix it. Is there something I'm missing that maybe didn't make to the blog post?
What browser are you using?
I'm not sure what could be the problem but make sure the submenu "#coolMenu ul" has "position: absolute".
I have the same issue, in ALL browsers (except IE; I don't have IE installed). I even tried copying and pasting the code, linking and un-linking the stylesheet, but the result is still the same. The sub menu is not positioned directly underneath it's parent, but to the right of it, indented slightly.
Here's a screenshot of what it looks like in chrome: http://ow.ly/i/cxv4
Ok, I found the problem. This is happening because you're not using the css reset.
I recommend always using a reset for consistency across browsers.
But, if you don't want to use it or you're using your own css reset and it's still happening just add "padding: 0;" to "#coolMenu ul" and it should work fine.
Thanks! Yeah I missed the line about the reset!
two basic questions
my animation part doesn't work
so where does the code beginning with $(function(){ go?
in a separate js folder? is so what do you name it?
and where exactly does the padding: 0 referred to above go?
there are a couple of sections which say #coolmenu ul
Hello.
Very nice tutorial! Thank You!
I have to say some words, though :)
I see more and more posts on usability of UI and one of the critics about menu is that it should not be "nervous", meaning - it should not open sub-menu on immediate "hover", but wait some time, because user may unintentionally hover the menu with mouse many times. The same is for "blur".
So, as an usability point - it would be "correct" to add some delay before opening the menu and closing it.
Just some thought.
You can use the hoverIntent plugin.
Yes, I was referring to something like that :)
Thank You.
Yes, I was learning to something likeit
Good tutorial, but its not working in IE6.
I think IE6 doesn't support child selectors.
The child selectors are easily swappable for ul li ul li styles etc so shouldn't be a barrier to getting it working on IE6. However, the li:hover will not function in IE6 and this requires a bit more of a workaround. You can use JavaScript to add a hover class (such as li.hover) to the li's on the mouseover event and remove it on the mouseout even. This way the styling will remain concise and the functionality consistent across all browsers.
Finally, if you want more nice usability tweaks such as delaying hiding/showing and also widening the sensitive areas of the menu so they don't disappear as soon as you roll slightly off them I have always found the Uvumi dropdown menu easy to implement using mootools. The advantage of this particular option is the ease of styling and the fact that the html remains clean and valid.
Thanks for sharing the fundamentals. It's easy to find hundreds of downloadable templates for cool looking dropdown menus, but to actually know how it operates and what's involved in its development is a much better resource.
Nice
I always find drop downs a little tricky especially when trying to get them to look and work the same in IE6. I have a HTML/CSS driven drop down I use normally with an alternative stylesheet for IE6. However the other day it was conflicting with my J Query, I might give this a try hopefully it works perfectly! I think adding J Query to your navigation always makes it look nicer and adds a little bit more animation to the rollover states.
I am trying to add a submenu to my menu. I have tried adding the ul inside of the ul but the only thing that
does is display the two submenu items visible below the main menu item. I tries using hide in the unordered
list but that hid the whole horizontal menu bar, not the two submenu items. I am sure it is a css styling problem I just don't know what it is. The problem I am running accross with instruction on this is that I already have a menu bar. I just want to add a drop donw to one of the blocks because I have 2 different pages I need to go to. All the instruction I am running across is building a whole menu bar which I already have. Any ideas?
Hi,
I am trying to add vertical menu for my website. I have used your horizonal menu bar and it has worked well. I need a vertical bar which does not use javascript. Can you direct me to right place?
-jody
Hi, Jody
This is my example of vertical menu based on this tutorial: http://jsfiddle.net/mickeyvip/tRbLv/
Hope it helps
Hi,
Very nice. I like the smooth effects of the jquery. Has anyone gotten this to work in ie6? Also, anyone successful in adding a submenu to the first submenu? Like to keep building on this terrific base. Thanks for contributing.
Lynne
thank you!
I can fix the IE6 finally...
change the css as below
#coolMenu {
float: left;
width: auto;
}
#coolMenu li {
width: 89px;
float: left;
}
#coolMenu > li {
float: left;
width: 89px;
}
Great tutorial. Easy to follow along, and to understand. Kudos!
Hello, thanks for your reply via email and Ive unlocked my site http://www.elaineckt.blogspot.com
I cant seem to move the navigation hover bar to the middle.
Even after coding , it doesnt work!!
My html goes:
#coolMenu,
#coolMenu ul {
list-style: none;
}
#coolMenu {
float: left;
}
#coolMenu > li {
float: left;
}
#coolMenu li a {
display: block;
height: 2em;
line-height: 2em;
padding: 0 1.5em;
text-decoration: none;
}
#coolMenu ul {
position: absolute;
display: none;
z-index: 999;
padding: 0;
}
#coolMenu ul li a {
width: 80px;
}
#coolMenu li:hover ul {
display: block;
}
/* Main menu
------------------------------------------*/
#coolMenu {
font-family: Arial;
font-size: 16px;
background: #EF0B0B;
position: center;
}
#coolMenu > li > a {
font-weight: bold;
}
#coolMenu > li:hover > a {
background: #EF0B0B;
color: #000;
position: center;
}
text-align: center;
/* Submenu
------------------------------------------*/
#coolMenu ul {
background: #EF0B0B;
}
#coolMenu ul li a {
color: #000;
}
#coolMenu ul li:hover a {
background: #EF0B0B;
}
Home
About Us
Services
Test
Test
Test
Incorporation
Contact Us
Help will be greatly appreciated :)
Hi there,
I chose not to include the reset.css and added the "padding: 0" instead, which fixed the alignment of the submenu, and love the way this functions in Firefox, but I cannot get it to work in IE (9).
here's where it's at if you have any suggestions: http://www.aapca3.org
thank you!
Hello Sir,
I wanted to thank you for this article, it was very helpful as it helped me fix issues that I encountered from my understanding of drop down menus.
I used to have position:relative on the coolmenu li, and position:absolute on the drop down menu. This created an issue where adding long texts in the drop down would not let the second menu to expand, but instead the text will break on the next line. Also, after using position absolute, I had to use a negative margin instead of the positioning property to style the menu according to my needs.
So an advise for people who may have made the same mistake as I, do not use position:relative on the first li in your drop down navigation lists. It prevents the drop down menu to resize on long text/sentences.
Also, am not sure if it was caused by the position:relative but, my drop down menu was going transparent on IE 7 before I removed the relative positioning.
Thanks again for this post.
thanks for sharing
Hi,
I am looking for how to add a submenu in my website.
I saw your directions and they are really helpful, but I want more help...
At first, I set up the HTML.
My code was like this
And then, accordance with your instructions I changed to
So, as you can see I add to "but2" the submenu "but8" and "but9".
Now, the CSS is like this
#menu{
background:url(images/menu_bg.jpg) top left no-repeat;
width:988px;
height:46px;
float:left;
/ float:none;
margin:40px 0 0 0;
/ margin:40px 0 0 3px;
padding:2px 0 0 4px;
}
#menu ul{
background:url(images/end_menu.gif) top right no-repeat;
overflow:hidden;
float:left;
padding:0 3px 0 0;
}
#menu li{
display:inline;
list-style-type:none;
}
ul#menu_nav
{
position:relative;
float:left;
width:790px;
padding:0;
margin:0;
list-style-type:none;
background-color:#000099;
}
ul#menu_nav li {float: left;
margin: 0; padding: 0;
border-right: 1px solid #555;}
ul#menu_nav li a.button
{
float:left;
text-decoration:none;
color:white;
background-color:#000099;
padding:0.2em 0.6em;
border-right:1px solid #CCCCCC;
font-family: Tahoma;
font-size: 11px;
font-style: normal;
font-weight: bold;
position: relative;
height: 21px;
line-height:1.85em;
}
ul#menu_nav li a:hover {
background-color:#F7F7F7;
color:#000099;
border-top:1px solid #CCCCCC;
}
ul#menu_nav li span{
float: left;
padding: 15px 0;
position: absolute;
left: 0; top:25px;
display: none;
width: 790px;
background: #F7F7F7;
color: #fff;
}
ul#menu_nav li:hover span { display: block; }
ul#menu_nav li span a { display: inline; }
ul#menu_nav li span a:hover {text-decoration: underline;}
#menu a{
display:block;
float:left;
}
.but1{background:url(images/but1.jpg) top left no-repeat;}
.but2{background:url(images/but2.jpg) top left no-repeat;}
.but3{background:url(images/but3.jpg) top left no-repeat;}
.but4{background:url(images/but4.jpg) top left no-repeat;}
.but5{background:url(images/but5.jpg) top left no-repeat;}
.but6{background:url(images/but6.jpg) top left no-repeat;}
.but7{background:url(images/but7.jpg) top left no-repeat;}
#menu a:hover, .active{
background-position:bottom left
}
So, I don't know WHAT I must ADD to CSS code in order the submenu to work normally.
Can you help me please to find a solution to my problem?
Thank you very much in advance!
Hi. great tutorial. I don't know much about CSS and this helped me understand it, and it's excatly what im looking for. I do have an issue an is that , when I hover over the MAIN MENU LINK the submenu dont appear. They are always showing up no matter if you hover over a link or click or do nothing. Also just below the main there is a div for the rest of the content ect. The sub menu is showing but behind that so you can't really see it
hi Cedric,
You have done a cool job. I added this menu to my own site.
Thanks,
Great article! But if I'm not mistaken, the "display: block" is not needed, as that's default and you've not set "display: inline" on any of the elements.
Sorry, my mistake. Inline is default.
Hi Cedric Ruiz,
Thanks for the great post. I tried a submenu to the submenu but it didnt work. Please can you help me on this. Thanks.
Don't forget, you can easily convert this into a tab menu by rounding the corners using CSS 3:
border-top-left-radius:5px;
border-top-right-radius:5px;
Hi,
First of all thank you for this excellent post.
I'm just wondering how you can add the possibility to highlight active (selected) menu item tab on first level?
Thank you in advance.
Great tutorial. Just what I needed.
What I need to change in the CSS, to make the submenu aligned to the right, instead of to the left side of the main menu?
Oh, right-alignment was easy enough.
Just alter these sections of the CSS:
#coolMenu > li {
float: right;
position:relative; /* NEW */
}
#coolMenu ul {
position: absolute;
display: none;
z-index: 999;
right: 1px; /* NEW */
}
With newer versions of jQuery, you should use:
$(function(){
$('#coolMenu').child('li').hover(function(){
$(this).find('ul')
.removeClass('noJS')
.stop(true, true).slideToggle('fast');
});
});
Correction to myself. I was having a problem of this setup causing a repeating flipping of the toggle when hovering over the menu. I eventually had to do this:
Remove the display so that default is to allow it to display
#coolMenu ul {
position: absolute;
z-index: 999;
}
In the script:
$(function(){
$('#coolMenu').children().hover(function(){
$(this).children('ul')
.stop(true, true).slideToggle('slow');
});
$('#coolMenu > li').children('ul').toggle();
});
//This does the same thing, but first toggles the display off naturally. Then the first toggle activated is "on".
I was having the same problem with the repeating toggle, this fixed it. Thanks!
Thanks for the tutorial! You made it very easy to get from A to B and I really appreciate it. One question - how would you configure the code to utilize a sub-level in a list? I mean, make another drop-down FROM a drop-down?
Thanks!
I'm having an issue of a blank space before each menu item, like it's expecting to have a bullet there and it's invisible. This wouldn't be a problem, but it offsets my list to the right about 30px. Any ideas how to fix this? Thanks!
Nevermind - fixed
http://www.alistapart.com/articles/taminglists/