Bare Bones CSS-based Drop-down

October 4th, 2012

Drop-downs are nothing new at this point. In fact, this trend that started to take off in the late 1990’s has seen many changes and evolution in it’s technology, development and design. Through the use of modern CSS, we are able to ditch the clunky JavaScript, Flash and Applet implementations of yesteryear.

Drop-down menus are extremely prolific, yet, there’s quite a few people that still don’t understand how they work. It’s a question I get a lot. Well, I decided to break it down in to it’s bare essentials for a horizontal navigation with a depth of 2:

Demo

Code

HTML

<ul id="nav">
    <li><a href="#">Test</a></li>
    <li><a href="#">Test Dropdown</a>
        <ul>   
            <li><a href="#">Test Drop</a></li>
            <li><a href="#">Test Dropdown #2</a>
                <ul>
                    <li><a href="#">Test Drop</a></li>
                    <li><a href="#">Test Drop</a></li>
                    <li><a href="#">Test Drop</a></li>
                </ul>
            </li>        
            <li><a href="#">Test Drop</a></li>
        </ul>
    </li>
    <li><a href="#">Test</a></li>
    <li><a href="#">Test</a></li>
</ul>​

CSS

#nav, #nav li {
    list-style:none;
    display:inline;    
}

#nav ul {
    display:none;    
}

#nav li:hover > ul {
    display: block;
    position: absolute;
    margin-top: -2px;  
}

As you can see, using a basic HTML list with a couple CSS properties, you can get yourself a drop down in no time at all. Of course, most of your time will be spent on the design and layout itself.

What’s the magic the makes it work? Well, it starts off by hiding all the <ul> elements under the main #nav ul, using display:none. This will hide as many sub-menus as you put in your HTML markup with ease. The next part is showing them again when ever you are hovering on any <li> element with <ul> children inside them, selecting it with the special “>” selector. We also move the margin up a little bit to account for any pixels in between the elements. Browsers are usually pretty good for accounting for this gap, but just this is just to make sure your hovers don’t lose focus. You may need to adjust this based on your design.

This entry was posted in Blog and tagged , .

3 Responses to Bare Bones CSS-based Drop-down

November 20th, 2012
Gordon Glapinski says:

Your solution is Brilliantly Simple!

BUT,
1/ I don’t understand why display:block; results in inline submenus
AND
2/ I don’t understand why my solution doesn’t work

HTML

Drop Down Menu, HORIZONTAL

<ul id="nav">
  <li><a href="#" rel="nofollow">Main 1</a>
    <ul class="submenu"><li><a href="#" rel="nofollow">Sub 1a</a></li>
    <li><a href="#" rel="nofollow">Sub 1b</a> </li>
    <li><a href="#" rel="nofollow">Sub 1c</a></li> 
    <li><a href="#" rel="nofollow">Sub 1d</a></li></ul>
  </li>

  <li><a href="#" rel="nofollow">Main 2</a>
    <ul class="submenu"><li><a href="#" rel="nofollow">Sub 2a</a> </li>
    <li><a href="#" rel="nofollow">Sub 2b</a> </li>
    <li><a href="#" rel="nofollow">Sub 2c</a> </li>
    <li><a href="#" rel="nofollow">Sub 2d</a></li></ul>
  </li>    

  <li><a href="#" rel="nofollow">Main 3</a></li>
</ul> ​​​​​​​​​​      

CSS

/* BAREST BONES VERSION of Horizontal Nav Menu with Horizontal Sub Menu */
/* The problem is that I'm expecting the drop down to show as a 2nd horizontal strip */
/* HOWEVER the sub menu is appearing as a vertical block!!! */
/* The CSS is deliberately stripped down to the absolute bare bones so that every cause-&gt;effect is easily visible */

#nav ul, li {

  /* to get rid of list bullets */
  list-style: none;
  
  /* to get rid of space to LHS &amp; RHS previously occuppied by bullets */
  padding-left: 1px;
  padding-right: 1px;
  /* just for clarity */
  margin-left: 1px;
  
  /* 'position: relative;' makes the later 'position: absolute;' work... WHY? */
  /* BECAUSE CSS rule is " 'position:absolute;' only works relative to 1st parent that is not static!"*/
  position: relative;

  /* float: left; here makes the top level of the menu horizontal !!! */
  float: left;
   
  /* green border to indicate elements to which this styling is applied */   
  border: 1px solid green;
  width: 60px;
  }
      
/* 'display:none;' to hide all ul's within the class(.) submenu */
ul.submenu {
  display: none;
  }

/* To (1) select 'ul' in div 'nav', (2) a mouse hover over one of its 'li' items triggers (3) styling of class 'submenu' */
ul#nav li:hover  .submenu {
  position: absolute;
  display: inline; 
  top: 20px;
  
  /* orange border to indicate elements to which this styling is applied */
  border: 1px solid orange;

  /* 'left: -2px;' used here to vertically line up submenu &amp; it's menu item */
  /* it's a css offset to counteract an inherited offset I can't identify */
  /* OR it may be an outline offset bug in Mozilla Firefox */
  /* A possible better solution is to apply css reset and thereby avoid odd tweaks! */
  /* For CSS Reset go to http://meyerweb.com/eric/tools/css/reset/ */
  left: -2px;
  }

/* SAD PART IS display:inline; NOR float:left; etc CAN MAKE THE SUBMENU HORIZONTAL */
Reply
November 22nd, 2012
admin says:

Hey there, I took a look at your problems here. Here’s the fix: http://jsfiddle.net/Drath/E9Lf7/

As you can see, it was you making the li elements position:relative and also forcing all ul elements to be width: 60px, even the submenus!

Reply
November 10th, 2013
change a tire says:

Thanks for the css code. That saved me while working on a client’s website. I thought there was something wrong with the function.php for the theme. But again thanks!!

Reply

Leave a Reply

*

*

TOP