Web Reference

Drop-Down Menus with CSS

Drop-down menus (sometimes called pop-up or pull-down menus) are popular on web sites that have a lot of pages for their ability to save space: dozens of links can be squeezed into a narrow horizontal (or in rare cases vertical) space that would normally contain only five or six. Unfortunately, drop-downs have their disadvantages too: most javascript-based menus tend to be complicated, hard to edit and won't function on browsers with javascript disabled; those that use only CSS are much simpler, but they won't work when viewed with Explorer for Windows (which, unfortunately is the most popular browser on the planet. Did I mention the Explorer sucks?). Fortunately there is solution; the folks at HTML Dog have come up with an ingenious CSS-based method that utilizes a simple javascript hack to trick Explorer into behaving. The finished result will look like this:

Procedure

  1. Open a new HTML document and save it as "cssDropDown.html" or something similar. I'd recommend putting the file in a folder called something like "dropDownMenus" in your root folder.
  2. Create a menu of links. The key here is to make each main link its own separate list <ul>. Sub-menus (those that will drop down) should also be separate lists, placed inside the list item (before the closing </li> tag) for each of the main categories. You can use the following markup to save time:
  3. <div id="container">

    <ul id="nav">
    <li><a href="#">Baseball</a>
    <ul>
    <li><a href="#">Yankees</a></li>
    <li><a href="#">Twins</a></li>
    <li><a href="#">Mets</a></li>
    </ul>
    </li>


    <li><a href="#">Football</a>
    <ul>
    <li><a href="#">Giants</a></li>
    <li><a href="#">Vikings</a></li>
    <li><a href="#">Jets</a></li>
    <li><a href="#">Steelers</a></li>
    <li><a href="#">Colts</a></li>
    </ul>
    </li>


    <li><a href="#">Hockey</a>
    <ul>
    <li><a href="#">Rangers</a></li>
    <li><a href="#">Wild</a></li>
    <li><a href="#">Islanders</a></li>
    <li><a href="#">Stars</a></li>
    </ul>
    </li>

    </ul>

    </div>

     

  4. Now we add some basic structure with CSS:
  5.  

    <style type="text/css">

    <!--

     

    #nav, #nav ul {
    float:left;
    padding: 0;
    margin: 0;
    list-style: none;
    }

     

    #nav a {
    display: block;
    width: 140px;
    line-height: 2em;
    padding-left: 10px;
    }

     

    #nav li {
    float: left;
    width: 150px; //this line is needed to keep it from breaking in Opera
    }

     

    -->

    </style>

    The width of course can be changed according to your design.

  6. Next we will add some visual styling (colors, fonts, etc.). These of course are not set in stone; in fact you should customize the look of your menus according to your design:
  7. #container {
    font-family: Arial, Helvetica, serif;
    font-size: .9em;
    font-weight: bold;

    }

     

    #nav, #nav ul {
    float:left;
    padding: 0;
    margin: 0;
    list-style: none;
    background-color: #ddd;
    }

     

    #nav a {
    display: block;
    width: 140px;
    line-height: 2em;
    padding-left: 10px;
    color: #330099;
    text-decoration: none;

    }

     

    #nav li {
    float: left;
    width: 150px; /* this line is needed to keep it from breaking in Opera */
    }

     

    #nav li:hover {
    background:#9999FF
    }

    Make sure you set the font size in the container's style, not the list's style. If you use ems or percentages for font size and put it in the <ul> style, every sublist will have text that is that much smaller (or larger). For example, if you set the font size to .8em, each sublist will display the text 80% smaller than its parent list.

  8. Now we need to hide the drop-down lists. In the past it was common to use display:none, but that has caused problems with accessibility. A better option is to shove the menus way off screen by using the margin property. Add these styles:
  9. #nav li ul {
    position: absolute;
    width: 150px;
    left: -999em;
    }

     

    #nav li:hover ul {
    left: auto;
    }

    The first rule hides all lists that are contained within other lists. The #nav li:hover rule causes the sub-menu lists to reappear when we mouse-over it's parent list item. However, Explorer does not recognize pseudo-styles for tags other than <a> so we need to add a bit of javascript to trick IE into seeing our hover command. In the <head>, after the closing </style> tag add the following code:

    <script type="text/javascript">
    <!--

     

    sfHover = function() {
    var sfEls = document.getElementById("nav").getElementsByTagName("LI");
    for (var i=0; i<sfEls.length; i++) {
    sfEls[i].onmouseover=function() {
    this.className+=" sfhover";
    }
    sfEls[i].onmouseout=function() {
    this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
    }
    }
    }

    if (window.attachEvent) window.attachEvent("onload", sfHover);

     

    -->

    </script>

    This creates a function that applies a class style called "sfhover" to all of the list items when they are moused-over, causing the submenus to appear, and removes the class style when moused-out.

  10. But to actually apply this function we need to make two small additions to our styles:
  11. #nav li:hover ul, #nav li.sfhover ul {
    left: auto;
    }

     

    #nav li:hover, #nav li.sfhover {
    background:#9999FF
    }

     

  12. Important: since the menu uses floats, make sure you add a clear:left to whatever element follows the menu in the markup.
  13. Go above and beyond: Experiment with colors, fonts, sizes. Add new menu items (and change the ones I provided). Try adding borders.
  14. Want to add another tier of menus (sub-sub menus that open to the side)? Check out the "Son of Suckerfish" tutorial at HTMLDog.com.

 

Back to the top