CSS2 Menu

by Granville Bonyata on January 25, 2013

By Nicholas Geiger

I found the ASP.NET Menu class on the 3.5 framework to be quite annoying because of how it caused distortions with surrounding elements. I tried fixing it with styling but was unable. Eventually I decided to build a menu using CSS2 as a replacement. As I’m happy with what I created, I’d like to share it with others.

Since there are so many variations of menus, I put good effort into describing how this menu is built.

The example was tested on Internet Explorer 9, Firefox 17.0.1, and Google Chrome 23.0.1271.97 m. The only difference between their renderings was a slight font weight.

The first three steps include two pieces of background styling to help show the dimensions of elements in the example. This should assist with understanding how the styling is combined to complete the example.

Step 1 is creating fundamental HTML like the html, head, and body elements. The menu is constructed from an ul element. This ul element is placed inside a div with padding merely to put some room between its edges and the edges of the browser.

Step 1 Code.


<!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>
        <title>CSS2 Menu</title>
    </head>
    <body>
        <form id="form1">
            <div style="padding:20px 0px 0px 20px;">
                <ul style="background-color:green;">
                    <li><a href="#">Menu</a>
                        <ul>
                            <li>
                                <a href="#">File</a>
                                <ul style="background-color:red;">
                                    <li><a href="#">Save</a></li>
                                    <li><a href="#">Exit</a></li>
                                </ul>
                            </li>
                            <li><a href="#">Edit</a></li>
                            <li><a href="#">View</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </form>
    </body>
</html>

Step 1 Image.
Step 1

In step 2, the class cssMenu is assigned to the top ul element to facilitate adjusting style within the head element of the HTML document. Also, a few unwanted visual aspects were removed. The list-item markers, margins, and padding were all removed from the ul elements. The block behavior of the ul elements was replaced with inline-table behavior to remove the extra space to the right of the element set. The text underlining and wrapping were removed from the hyperlink elements. All of this causes the menu to become bare links which are horizontally thinned and left-aligned.

Step 2 Code.


<!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>
        <title>CSS2 Menu</title>
        <style type="text/css">
            ul.cssMenu
            {
                display:inline-table; /* Replace block behavior with inline-table behavior. */
            }
            
            ul.cssMenu, .cssMenu ul
            {
                list-style:none; /* Remove list-item markers. */
                margin:0px;
                padding:0px;
            }

            .cssMenu a
            {
                text-decoration:none; /* Remove underlining. */
                white-space:nowrap; /* Remove text wrapping. */
            }
        </style>
    </head>
    <body>
        <form id="form1">
            <div style="padding:20px 0px 0px 20px;">
                <ul class="cssMenu" style="background-color:green;">
                    <li><a href="#">Menu</a>
                        <ul>
                            <li>
                                <a href="#">File</a>
                                <ul style="background-color:red;">
                                    <li><a href="#">Save</a></li>
                                    <li><a href="#">Exit</a></li>
                                </ul>
                            </li>
                            <li><a href="#">Edit</a></li>
                            <li><a href="#">View</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </form>
    </body>

Step 2 Image.
Step 2

In step 3, some positioning is added to place each sub menu (ul element) to the right of their parent menu item (li element) so that their tops are aligned. This is done first by relatively positioning the li elements. Then the ul elements are absolutely positioned. This combination of relative positioning the parent and absolute positioning the child causes the child to be absolute positioned within the parent li element instead of the within html element. By doing this, the ul element can be absolutely positioned to the right side of the parent by setting the left attribute to 100% and aligned with the top of the parent by setting the top attribute to 0px. The only difference between this and the example is that the top attribute is set to -1px because one of the borders seems to cause the child to be a pixel lower than the parent.

Step 3 Code.


<!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>
        <title>CSS2 Menu</title>
        <style type="text/css">
            ul.cssMenu
            {
                display:inline-table; /* Replace block behavior with inline-table behavior. */
            }
            
            ul.cssMenu, .cssMenu ul
            {
                list-style:none; /* Remove list-item markers. */
                margin:0px;
                padding:0px;
            }

            .cssMenu li
            {
                position:relative;
            }

            .cssMenu ul
            {
                position:absolute;
                left:100%;
                top:-1px;
            }

            .cssMenu a
            {
                text-decoration:none; /* Remove underlining. */
                white-space:nowrap; /* Remove text wrapping. */
            }
        </style>
    </head>
    <body>
        <form id="form1">
            <div style="padding:20px 0px 0px 20px;">
                <ul class="cssMenu" style="background-color:green;">
                    <li><a href="#">Menu</a>
                        <ul>
                            <li>
                                <a href="#">File</a>
                                <ul style="background-color:red;">
                                    <li><a href="#">Save</a></li>
                                    <li><a href="#">Exit</a></li>
                                </ul>
                            </li>
                            <li><a href="#">Edit</a></li>
                            <li><a href="#">View</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </form>
    </body>
</html>

Step 3 Image.
Step 3

In step 4, the look of the menu items are improved. A background color and border are added to the ul elements. Font, text color, and padding are added to the hyperlinks. Since the hyperlinks are displayed inline by default, they need to be displayed as block elements to allow the top and bottom padding in the hyperlinks to appear.

Step 4 Code.


<!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>
        <title>CSS2 Menu</title>
        <style type="text/css">
            ul.cssMenu
            {
                display:inline-table; /* Replace block behavior with inline-table behavior. */
            }
            
            ul.cssMenu, .cssMenu ul
            {
                background-color:#E0EBEB;
                border:solid 1px black;
                list-style:none; /* Remove list-item markers. */
                margin:0px;
                padding:0px;
            }

            .cssMenu li
            {
                position:relative;
            }

            .cssMenu ul
            {
                position:absolute;
                left:100%;
                top:-1px;
            }

            .cssMenu a
            {
                color:black;
                display:block;
                font-family:arial;
                font-size:14px;
                font-weight:normal;
                padding:10px 20px;
                text-decoration:none; /* Remove underlining. */
                white-space:nowrap; /* Remove text wrapping. */
            }
        </style>
    </head>
    <body>
        <form id="form1">
            <div style="padding:20px 0px 0px 20px;">
                <ul class="cssMenu">
                    <li><a href="#">Menu</a>
                        <ul>
                            <li>
                                <a href="#">File</a>
                                <ul>
                                    <li><a href="#">Save</a></li>
                                    <li><a href="#">Exit</a></li>
                                </ul>
                            </li>
                            <li><a href="#">Edit</a></li>
                            <li><a href="#">View</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </form>
    </body>
</html>

Step 4 Image.
Step 4

In step 5, the interactive aspects are added. A darker background color is added to any li element that is hovered. Since each child li element is contained inside all their parents, all parent li elements will remain highlighted with this darker color while the cursor is navigating child elements of them. Lastly, the child menu items are hidden until their immediate parent is hovered. To hide the child menu items, the display attribute of all ul elements, except for the top parent, are set to none. To reveal menu items when their immediate parent is hovered, the selector combination “.cssMenu li:hover>ul” is used to set the display attribute of those elements to block.

Step 5 Code.


<!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>
        <title>CSS2 Menu</title>
        <style type="text/css">
            ul.cssMenu
            {
                display:inline-table; /* Replace block behavior with inline-table behavior. */
            }
            
            ul.cssMenu, .cssMenu ul
            {
                background-color:#E0EBEB;
                border:solid 1px black;
                list-style:none; /* Remove list-item markers. */
                margin:0px;
                padding:0px;
            }

            .cssMenu li
            {
                position:relative;
            }

            .cssMenu ul
            {
                display:none;
                position:absolute;
                left:100%;
                top:-1px;
            }

            .cssMenu a
            {
                color:black;
                display:block;
                font-family:arial;
                font-size:14px;
                font-weight:normal;
                padding:10px 20px;
                text-decoration:none; /* Remove underlining. */
                white-space:nowrap; /* Remove text wrapping. */
            }

            .cssMenu li:hover>ul
            {
                display:block;
            }

            .cssMenu li:hover
            {
                background-color:#A3C2C2;
            }
        </style>
    </head>
    <body>
        <form id="form1">
            <div style="padding:20px 0px 0px 20px;">
                <ul class="cssMenu">
                    <li><a href="#">Menu</a>
                        <ul>
                            <li>
                                <a href="#">File</a>
                                <ul>
                                    <li><a href="#">Save</a></li>
                                    <li><a href="#">Exit</a></li>
                                </ul>
                            </li>
                            <li><a href="#">Edit</a></li>
                            <li><a href="#">View</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </form>
    </body>
</html>

Step 5 Image.
Step 5

Previous post:

Next post: