Search code examples
csshtmlmenustylesheetsubmenu

HTML/CSS: how do I properly style this menu?


I am learning to create CSS menus WITHOUT floats. I got a partially "working" menu so far. However, the main menu's borders are separated. Also the submenu's borders are sized in half and the hover's background color is not working. At the same time, the sub-sub menu is not working

I am also trying to simplify the CSS code with a .menu .submenu .sub-submenu classes.

jsFiddle: http://jsfiddle.net/vn64H/1/


HTML

<!DOCTYPE html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Title: Navigation menu</title>

    <link rel="stylesheet" type="text/css" href="menu.css">
</head>
<body>

<!-- START: menu -->
<ul id="nav">
    <li class="menu"><a href="#">Home</a></li>
    <li class="menu"><a href="#">Main Menu 2</a>
        <ul class="submenu">
            <li><a href="#">Sub Menu 2.1</a></li>
            <li><a href="#">Sub Menu 2.2</a></li>
            <li><a href="#">Sub Menu 2.3</a>
                <ul>
                <li><a href="#">Sub-Sub Menu 2.3.1</a></li>
                <li><a href="#">Sub Menu 2.3.2</a></li>
                <li><a href="#">Sub Menu 2.3.</a></li>
                </ul>
            </li>
            <li><a href="#">Sub Menu 2.4</a></li>
            <li><a href="#">Sub Menu 2.5</a></li>
            <li><a href="#">Sub Menu, Some Sample Text  2.6</a></li>
            <li><a href="#">Sub Menu, Sample Text  2.7</a></li>
        </ul>
    </li>
    <li class="menu"><a href="#">Main Menu 3</a>
        <ul class="submenu">
            <li><a href="#">Sub Menu 3.1</a></li>
            <li><a href="#">Sub Menu 3.2</a></li>
            <li><a href="#">Sub Menu 3.3</a></li>
            <li><a href="#">Sub Menu 3.5</a></li>
            <li><a href="#">Sub Menu 3.6</a></li>
            <li><a href="#">Sub Menu 3.7</a></li>
        </ul>
    </li>
    <li class="menu"><a href="#">Main Menu 4</a>
        <ul class="submenu">
            <li><a href="#">Sub Menu 4.1</a></li>
            <li><a href="#">Sub Menu 4.2</a></li>
            <li><a href="#">Sub Menu Sample Text 4.3</a></li>
            <li><a href="#">Sub Menu 4.4</a></li>
            <li><a href="#">Sub Menu 4.5</a></li>
            <li><a href="#">Sub Menu 4.6</a></li>
            <li><a href="#">Sub Menu 4.7</a></li>
            <li><a href="#">Sub Menu 4.8</a></li>
        </ul>       
    </li>
    <li class="menu"><a href="#">Menu 5</a></li>
    <li class="menu"><a href="#">Menu 6</a></li>
    <li class="menu"><a href="#">Contact</a></li>
</ul> <!-- /#menu -->
<!-- END: menu -->


</body>
</html>


CSS

@charset "utf-8";
#nav {
    background-color: #000;
    position: relative;

    font-family: Arial, Helvetica, sans-serif; 
    font-size: 0.975em;
    text-align: left;
    display: block;
    border: 1px dotted #cccccc;
    padding: 0;
    margin: 0;
}
#nav a {
    color: #fff;
    text-decoration: none;
}
#nav li {
    color: #fff;
    text-align: left;

    width: 110px;
    border: 1px solid #CCCCCC;
    list-style-type: none;
    padding: 0;
    margin: 0;
    display: inline-block;
}

/*Sub menu */
#nav li ul {
    color: navy;
    text-align: left;
    list-style-type: none;

    width: 200px;
    border: 1px solid #000;
    padding: 0;
    margin: 0;

    display: none;
    position: absolute;
    background-color: #990000;
}
#nav li ul a {
    display: inline-block;
}
#nav li:hover ul {
    visibility: visible;
    display: block;
    background-color: #E6B800;
}
#nav li:hover ul li {
    background-color: #E6B800;
}

/*Sub-sub menu */
#nav li ul li ul li a {
    display: none;
}
#nav li ul li ul li:hover {
    visibility: visible;
    display: block;
    background-color: #E6B800;
}
#nav li ul li ul li:hover ul li {
    background-color: #E6B800;
}

Solution

  • The main-menu borders are separated because the <li>s are inline-blocks with white-space in between them. Inline-blocks work like words in a text stream, so any white space, such as the line breaks you have in there, will be interpreted as text-space characters. The only way around that while keeping them inline-blocks is to put all the <li>'s on one line with zero white-space in between. Why do you want to avoid floats? That would be your best option.

    The sub-menu items are half-spaced because the container has width of 200px, but each item is an inline-block with no width specified. Make them display:block isntead and they will expand out to the edges of the container.

    Do apply your sub- and sub-sub-menu classes, that will be easier to see and work with than so many nested selectors.

    Also: use teh the child selector syntax, e.g.: ul#nav > li it will apply the relevant styles only to the child items, and not to the grand-children, etc.

    UPDATE
    In asnwer to mcknz' question, I would place float:left on #nav li instead of display:inline-block. This solves 2 problems:

  • The unintended spacing between the menu items will disappear, regardless of white-space in the HTML. You can now control their spacing precisely with margins.
  • IE7 will not apply inline-block to list-items -- or any elements that are not natively inline (see: http://fourwhitefeet.com/2009/02/css-display-inline-block-in-ie7/)
  • Important note: You will need to specify the height of the #nav explicitly now, because non-floating parents of floating elements collapse (see: Why do non-floating parents of floating elements collapse?).

    ...also: you can safely remove subsequent text-align: left; declarations once you've applied it to #nav, this property inherits down to all nested elements, unless, of course, you have an intervening layer with text aligned left or center. Properties that inherit are listed here: http://www.communitymx.com/content/article.cfm?cid=2795d