Create simple CSS horizontal navigation menu with drop down submenu

Author : Bikram Choudhury . He teaches various computer subjects and programming languages like C C++ / Java / PHP MySQL / HTML / HTML5 /CSS /JavaScript / jQuery online. Visit www.onlinecomputerteacher.net for details.

About this tutorial : Please check the completed menu here, your ultimate menu will be this . At the bottom whole code given.

You will be able to create a top level horizontal navigation menu which may or maynot have submenus. This type of menus sometimes called as NAV menu or suckerfish menu… when you will mouse over on them, then sub menu will be shown (if that menu item has sub level menu). I have kept this menu as simple as possible to look. No effects, background has been used. These will be added in future tutorials. But this is the basic tutorial.

In this tutorial we have created and shown submenus upto sub menu level 4. The initial horizontal navigation menu is called top level menu item and each menu item in it can have upto 4 level down sub menus.Though you can go more to create few levels more if required so.


The first step: create the top level menu item. Though I am calling it a menu, but this is nothing but an unordered list or UL block which contains LI elements.

The HTML code : Create a basic menu like the following.. always put the code in HTML section of a webpage and put it under BODY tag. You can wrap the following code in a DIV tag also. But that is a different article.

<ul id="nav">
  <li><a href="#">0. Home</a></li>
  <li><a href="#">1. L1- (upto 3 level sub menu will be under it)</a></li>
  <li><a href="#">2. Level-1</a></li>
  <li><a href="#">3. L1-(upto 4 level sub menu will be under it)</a></li>
</ul>

This will show like the following menu. This will be the top level menu, now its vertical, but soon it will be horizontal. For your convenience I have mentioned the submenu information in menu text.

The above menu appears like this in Web Browsers:

Normally these menus are shown vertically. Now we shall add few submenus (sub UL blocks under LI elements ) under them as given below.

How to add sublist under a list item –
<ul>
  <li><a href="http://www.rankingoogle.com">1. Get Google top ranking</a>
    <ul>
      <li><a href="http://www.rankingoogle.com/seo_services.php">1.1 Services</a></li>
      <li><a href="http://www.rankingoogle.com/seoupdation/">More about seo</a></li>
    </ul>

  <li><a href="http://www.rankingoogle.com/seo/top_10_ranking.php">Top 10 search engine ranking</a></li>
</ul>

The above menu is a normal menu (or Unordered List, what ever you say it. )

Notice: after </a> we have inserted a UL block in italics here, which is inside the <LI></LI>, this is the basic syntax of a submenu under a list item (LI).

In the following example we have created a fresh menu and the first sub menu appears under 2nd List Item of top level nav menu which is UL (Unordered List ) of ID = nav. You can put any URL , e.g http://www.google.com or any relative or absolute URL instead of # in list items href section..

The HTML code :

<ul id="nav">
<li><a href="#">0. Home</a></li>
<li><a href="#">1. L1- (3 menus will be under this menu)</a>
<ul>
  <li><a href="#">1.1. Sub-Level-1</a></li>
  <li><a href="#">1.2. SL-l (2 menus will be under this menu)</a></li>
  <li><a href="#">1.3. Sub-Level-1</a></li>
  <li><a href="#">1.4. Sub-Level-1</a></li>
 </ul>

</li>
<li><a href="#">2. Level-1</a></li>
<li><a href="#">3. L1-(4 menus will be under this menu)</a>
<ul>
  <li><a href="#">3.1. Sub-Level-1</a></li>
  <li><a href="#">3.2. Sub-Level-1</a></li>
  <li><a href="#">3.3. SL-1- (3 menus will be under this menu)</a></li>
  <li><a href="#">3.4. Sub-Level-1</a></li>
 </ul>

</li>

</ul>

The above menu appears like this in Web Browsers:


Now expand the list more by adding more sub menus. So carry on creating sub menus and finally build a menu using the folloing :

This is the HTML code of the full menu (given below), we didnot use any extra tags except UL/ LI. No stylesheet used upto this moment.

HTML Code :

<ul id="nav">
 <li><a href="#">0. Home</a></li>
<li><a href="#">1. L1- (3 menus in it)</a>
  <ul>
    <li><a href="#">1.1. Sub-Level-1</a></li>
    <li><a href="#">1.2. SL-l (2 menus in it)</a>
       <ul>
         <li><a href="#">1.2.1. SL-2- (1 menu in it)</a>
          <ul>
           <li><a href="#">1.2.1.1. Sub-Level-3</a></li>
           <li><a href="#">1.2.1.2. Sub-Level-3</a></li>
           <li><a href="#">1.2.1.3. Sub-Level-3</a></li>
           <li><a href="#">1.2.1.4. Sub-Level-3</a></li>
          </ul>
         </li>
         <li><a href="#">1.2.2. Sub-Level-2</a></li>
         <li><a href="#">1.2.3. Sub-Level-2</a></li>
         <li><a href="#">1.2.4. Sub-Level-2</a></li>
       </ul>
    </li>
    <li><a href="#">1.3. Sub-Level-1</a></li>
    <li><a href="#">1.4. Sub-Level-1</a></li>
  </ul>
</li>
<li><a href="#">2. Level-1</a></li>
<li><a href="#">3. L1-(4 menus in it)</a>
  <ul>
    <li><a href="#">3.1. Sub-Level-1</a></li>
    <li><a href="#">3.2. Sub-Level-1</a></li>
    <li><a href="#">3.3. SL-1- (3 menus in it)</a>
       <ul>
         <li><a href="#">3.3.1. Sub-Level-2</a></li>
         <li><a href="#">3.3.2. SL-2 (2 menus in it)</a>
          <ul>
           <li><a href="#">3.3.2.1. SL-3 (1 menu in it)</a>
             <ul>
                <li><a href="#">3.3.2.1.1 Sub-Level-4</a></li>
                <li><a href="#">3.3.2.1.2 Sub-Level-4</a></li>
                <li><a href="#">3.3.2.1.3 Sub-Level-4</a></li>
             </ul>
           </li>
           <li><a href="#">3.3.2.2 Sub-Level-3</a></li>
           <li><a href="#">3.3.2.3 Sub-Level-3</a></li>
           <li><a href="#">3.3.2.4 Sub-Level-3</a></li>
          </ul>

         </li>
         <li><a href="#">3.3.3. Sub-Level-2</a></li>
         <li><a href="#">3.3.4. Sub-Level-2</a></li>
       </ul>
    </li>
    <li><a href="#">3.4. Sub-Level-1</a></li>
  </ul>
</li>
<li><a href="#">4. Level-1</a></li>
</ul>

The output in browser :

The menu is quite odd looking now and we shall make it good looking very soon. Now the ball goes to CSS ‘s court. Lets play with CSS to show it right.


Now our job will be to make the above menu into a horizontal NAV menu by adding styles as mentioned below.

Make the top level menu visible, all other sub menus will not be shown. Add the following CSS inside the HEAD section to add styles : Check here how the menu looks now after adding the styles mentioned below

<style type="text/css">
* {
   margin:0;
   padding:0;
}
#nav ul {
      list-style-type:none;
      display:none; /* hides all sub menus descendant of UL of id = nav */
}
#nav li {
      float:left; /* makes menus to appear side by side */
      position:relative;
      width:12em; /* for FLOAT elements width is must */
}
</style>

Explanation : margin and padding is set to 0 for all elements initially, this is a preliminary optional step to reset margin and padding. #nav is the id of top level UL block, so all sub menus are invisible and not displayed by the code, only UL of id = nav will be displayed.

#nav ul {
      list-style-type:none;
      display:none; /* hides all sub menus descendant of UL of id = nav */
}

The next most important step is the following –
#nav li {
      float:left;
      position:relative;
      width:12em;
}

It makes the top level menu’s list items to appear side by side by floating them to left, normally LI are block elements, so they normally appear vertically, but by float: left we make them to appear horizontally. Keep in mind float elements must use a width implicitly or explicitly, here shown explicitly.

position : relative controls the blocks inside the LI element, this is important when UL appears inside UL for submenus. relatively positioned elements are shown normally in the normal flow, then reposition them according to left: and top: property.


Step-2 : Now add more styles and after addition the navigation menu looks like this . The sub menu under top level menu, i.e sub-menu-level-1 will be displayed, but beyond that any sub menu will not be displayed.

#nav li:hover ul{ display:block; /* level 1 menu will be displayed */ }
#nav li:hover ul ul { display: none; /* level 2 onwards sub menu will hidden*/ }

The whole stylesheet will be as follows :

<style type="text/css">
* {
  margin:0; padding:0;
}

#nav ul {
    list-style-type:none;
    display:none;
}
#nav li {
    float:left;
    position:relative;
    width:12em;
}
/* level 1- sub menu will be displayed, but sub sub menu will not be displayed */
#nav li:hover ul {
display:block; /* level 1 menu will be displayed */
}
#nav li:hover ul ul {
         display: none;
/* level 2 onwards sub menu will hidden*/
}
</style>

Explanation : When you mouse over a LI item which is a descendant element of a UL block of id nav , ( i.e top level UL block or top level menu ) then the sub-level-1 sub menu will be displayed. This sub menu is the UL block under of top level menu (UL#nav) , which is also a descendant of top level LI elements, will be displayed by this style code :

#nav li:hover ul { display:block; /* sub-level-1 sub menu will be displayed */ }

But any UL which is a descendant of that UL will not displayed because of this code –

#nav li:hover ul ul { display: none; /* sub-level-2 onwards sub menu will be hidden*/ }

Check it here : the navigation menu looks like this


Step 3 :

Now by adding the following CSS upto sub level menu 2 level down will be shown. Sub menu level 1 appears under top level menu items, and under sub menu level 1, sub menu 2 appears. Here two new style blocks introduced :

ul#nav li ul li:hover ul {
        display:block;
        position:absolute;
        top:0;
        left:12em;
}

#nav li ul li:hover ul ul { display: none }

Explanation : 2nd level menu when hovered , that is mouse overed, then the UL inside that will be visible, but beyond that any UL block will not be displayed. First UL#nav LI denotes top level menu ( can be used as #nav li also ), the second UL LI:hover means when a sub menu level -1 item is hovered, then the next level sub menu will be shown, i.e sub menu level 2.

But because of position : relative property of LI (of sub menu level – 1, e.g SL-1), which is a container of sub menu level 2- UL block, then this UL block is positioned according to LEFT and TOP property , i.e Top: 0 and Left: 12em; here 12 em is the width of all LI elements. So sub menu level 2 elements appears beside sub menu level -1 menu / list item.

Now the menu looks like this : The full style sheet portion given below –

<style type="text/css">
* {
   margin:0; padding:0;
}

#nav ul {
     list-style-type:none;
     display:none;
}
#nav li {
     float:left;
     position:relative;
     width:12em;
}
/* level 1- sub menu will be displayed, but sub sub menu will not be displayed */
#nav li:hover ul{
           display:block; /* level 1 menu will be displayed */
}
#nav li:hover ul ul {
           display: none; /* level 2 onwards sub menu will hidden*/
}

/* level 2- sub menu will be displayed, but beyond it will not be */
#nav li ul li:hover ul {
          display:block;
          position:absolute;
          top:0;
          left:12em;
}
#nav li ul li:hover ul ul { display: none }
</style>


Final Step : add the following styles to show more sub menus

/* level 3- sub menu will be displayed */
#nav li ul li ul li:hover ul{
          display:block;
          position:absolute;
          top:0;
          left:12em;
}
/* Beyond level-3 submenu no submenu will not be */
#nav li ul li ul li:hover ul ul { display: none }

/* level 4- sub menu will be displayed */
#nav li ul li ul li ul li:hover ul {
          display:block;
          position:absolute;
          top:0;
          left:12em;
}
/* Beyond level-4 submenu no submenu will not be */
#nav li ul li ul li ul li:hover ul ul { display: none }

So the Final HTML Code + Stylesheet will be the following :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
* {
          margin:0;
           padding:0;
}

#nav ul {
          list-style-type:none;
          display:none;
}
#nav li {
          float:left;
          position:relative;
          width:12em;
}

/* level 1- sub menu will be displayed, but sub sub menu will not be displayed */
#nav li:hover ul { display:block; /* level 1 menu will be displayed */ }
#nav li:hover ul ul { display: none; /* level 2 onwards sub menu will hidden*/ }

/* level 2- sub menu will be displayed, but beyond it will not be */
#nav li ul li:hover ul {
          display:block;
          position:absolute;
          top:0;
          left:12em;
}
#nav li ul li:hover ul ul { display: none }

/* level 3- sub menu will be displayed, but beyond it will not be */
#nav li ul li ul li:hover ul{
          display:block;
          position:absolute;
          top:0;
          left:12em;
}
#nav li ul li ul li:hover ul ul { display: none }

/* level 4- sub menu will be displayed, but beyond it will not be */
#nav li ul li ul li ul li:hover ul {
          display:block;
          position:absolute;
          top:0;
          left:12em;
}
#nav li ul li ul li ul li:hover ul ul {
           display: none;
}
</style>
</head>
<body>

<ul id="nav">
 <li><a href="#">0. Home</a></li>
<li><a href="#">1. L1- (3 menus in it)</a>
  <ul>
    <li><a href="#">1.1. Sub-Level-1</a></li>
    <li><a href="#">1.2. SL-l (2 menus in it)</a>
       <ul>
         <li><a href="#">1.2.1. SL-2- (1 menu in it)</a>
          <ul>
           <li><a href="#">1.2.1.1. Sub-Level-3</a></li>
           <li><a href="#">1.2.1.2. Sub-Level-3</a></li>
           <li><a href="#">1.2.1.3. Sub-Level-3</a></li>
           <li><a href="#">1.2.1.4. Sub-Level-3</a></li>
          </ul>
         </li>
         <li><a href="#">1.2.2. Sub-Level-2</a></li>
         <li><a href="#">1.2.3. Sub-Level-2</a></li>
         <li><a href="#">1.2.4. Sub-Level-2</a></li>
       </ul>
    </li>
    <li><a href="#">1.3. Sub-Level-1</a></li>
    <li><a href="#">1.4. Sub-Level-1</a></li>
  </ul>
</li>
<li><a href="#">2. Level-1</a></li>
<li><a href="#">3. L1-(4 menus in it)</a>
  <ul>
    <li><a href="#">3.1. Sub-Level-1</a></li>
    <li><a href="#">3.2. Sub-Level-1</a></li>
    <li><a href="#">3.3. SL-1- (3 menus in it)</a>
       <ul>
         <li><a href="#">3.3.1. Sub-Level-2</a></li>
         <li><a href="#">3.3.2. SL-2 (2 menus in it)</a>
          <ul>
           <li><a href="#">3.3.2.1. SL-3 (1 menu in it)</a>
             <ul>
                <li><a href="#">3.3.2.1.1 Sub-Level-4</a></li>
                <li><a href="#">3.3.2.1.2 Sub-Level-4</a></li>
                <li><a href="#">3.3.2.1.3 Sub-Level-4</a></li>
             </ul>
           </li>
           <li><a href="#">3.3.2.2 Sub-Level-3</a></li>
           <li><a href="#">3.3.2.3 Sub-Level-3</a></li>
           <li><a href="#">3.3.2.4 Sub-Level-3</a></li>
          </ul>

         </li>
         <li><a href="#">3.3.3. Sub-Level-2</a></li>
         <li><a href="#">3.3.4. Sub-Level-2</a></li>
       </ul>
    </li>
    <li><a href="#">3.4. Sub-Level-1</a></li>
  </ul>
</li>
<li><a href="#">4. Level-1</a></li>
</ul>

</body>
</html>

Please check the completed menu here, your ultimate menu will be this