CSS menu step by step
An example of a typical tabbed menu with procedure explained from initial concept to the final code.
Preparation
- Grab a piece of paper and a pencil or pen and draw a few ideas of how you want to structure the menu. This step can be skipped if you know exactly what you're going to do.
- Load Photoshop or other image editor and redraw your menu as you want it to see on the page.
- Open your favourite XHTML editor and create structure for the menu in XHTML. While creating structure it's important to understand that it has to be as simple as possible and make sense when styles are turned off. Imagine browsing the page you're creating via mobile or hand-held, how would you easily navgate your page so it doesn't confuse the hell out of you.
Coding
In our example we have a logo, utility links (links that are not related to any section and should be available from any page), main sections of the web site and sub sections is available.
The logo should wrap up the whole page, meaning it should visually suggest that it is on the top of the whole document and the content below. In stripped version we use text replacement (First level heading) for logo.

Below is the XHTML structure of our menu.
<h1><a href="#">Logotype</a></h1>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">My account</a></li>
<li><a href="#">Help</a></li>
<li><a href="#">Contact us</a></li>
</ul>
<ul>
<li><a href="#">Section 1</a></li>
<li><a href="#">Section 2</a></li>
<li><a href="#">Section 3</a></li>
<li><a href="#">Section 4</a></li>
</ul>
<ul>
<li><a href="#">Sub Section 1</a></li>
<li><a href="#">Sub Section 2</a></li>
<li><a href="#">Sub Section 3</a></li>
<li><a href="#">Sub Section 4</a></li>
</ul>
Defaults
First of all, we will set default setting for <body> and all inherited elements. Margins and font properties is a good start.
body {margin: 0; padding: 0; font: 100% arial, sans-serif;}
Logo
To create a logo with text replacement we add id to our heading:
<h1 id="logo"><a href="#">Logotype</a></h1>
In #logo rule we reset the margin for <h1>. Reset the font-size and position the element. Because the logo is the top level element and only skies are above, we position it against the body's viewport with relative values, dependent on elements font-size for nice scaling.
#logo {
font-size: 100%;
margin: 0;
position: absolute;
top: 1em;
left: 1.5em;
}
Because logo is actually a link and is wrapped in <a> we will need to style in order to remove the text and replace it with an image.
#logo a {
display: block;
text-indent: -9000px;
background: url(logo.png) 0 0 no-repeat;
width: 100px;
height: 25px;
}
We convert the anchor into block element, apply a background image of the logo, set the width and height of the image and remove the text by declaring text-indent propery to be -9000, effectively pushing it outside the screen boundaries.
Images
Next we slice images in Photoshop to use them in the menu. The follwing is the chart of images we use in our menu. Notice the size of image files. Blue background is introduced for clarity.
Menu set ups
Next we set up the lists for the menu. Reset the margins and remove the list-style from our menus, also, we declare the font-weight for lists.
#utility, #tab-nav, #tab-subnav ul {
list-style: none;
margin: 0;
font-weight: bold;
}
Next, we choose which items should be floated. Now there's one thing to remember about floats: floated elements get out of normal document flow, so if we place floated block inside a container the container's height will be 0, unless there's another unfloated element within the same container. However, floated elements expand the floated containers, so the trick is to float the container in order to expand it to fit the floated element inside it.
#nav, #utility li, #tab-nav li, #tab-nav a, #tab-subnav ul li {
float: left
}
Here we introduce a wrapping div in order to keep the floating list to the right and float the list items to the left, thus creating a left aligned menu for main sections. Notice that #nav is the container for both lists so it expands to the height of sections menu.
<div id="nav">
<h1 id="logo"><a href="#">Logotype</a></h1>
<ul id="utility">
<li id="ut-home"><a href="#">Home</a></li>
<li id="ut-acc"><a href="#">My account</a></li>
<li id="ut-help"><a href="#">Help</a></li>
<li id="ut-cont"><a href="#">Contact us</a></li>
</ul>
<ul id="tab-nav">
<li id="nav-sec1"><a href="#">Section 1</a></li>
<li id="nav-sec2"><a href="#">Section 2</a></li>
<li id="nav-sec3"><a href="#">Section 3</a></li>
<li id="nav-sec4"><a href="#">Section 4</a></li>
</ul>
</div>
Utility menu
We are going to position utility list to the top right corner as it will not be dependant on any expanding elements. Also we're going to add id to list items to be able to pick out the active ones based on the information from parent elements (we can use <body> for this task. Add borders on the left, background colour and bottom and pading around the list items.
#utility {
background: #508b21;
padding: 3px 5px;
border-bottom: 1px solid #36670f;
border-left: 1px solid #36670f;
position: absolute;
right: 0;
}
Next we add background colour to the wrapping div together with the image of line at the bottom. We add image to be able to overlap it with our tabs in order to create visual similarity with real world tabs. We also apply 100% value to width to extend it to the full width of the viewport.
#nav {
width: 100%;
background: #7DBE3C url(bottom-line.png) bottom left repeat-x;
}
We're going style list styles. First we need to set the font-size based on <body>. We will add padding of 7 px to the left and right of individual list items and dividing border to the left of each item.
#utility li {
font-size: 70%;
padding: 0 7px;
border-left: 1px solid #bcdda2;
}
Now we're going to remove the dividing border of the first element of utility menu (as well as submenu for later).
#utility li#ut-home, #tab-subnav ul #sub-sec1 {border: none}
The following two rules style the actual utility links. Set the colour for links and hover states.
#utility li a {color: #bcdda2}
#utility li a:hover {color: #fff}
Top level menu
The next piece of code is responsible for stylying the main sections menu.
#tab-nav { float: right; padding: 2em .7em 0 0 }
#tab-nav li {
margin: 0 0 0 1px;
padding: 0 1px;
font-size: 85%;
background: #c5e1ae;
border: 1px solid #508b21;
border-bottom: none;
}
#tab-nav a {
padding: 5px 12px;
text-decoration: none;
background: #c0dfa6 url(tab.png) 0 0 repeat-x;
}
First we do float:right to whole menu to position it against the right side of the viewport, adding padding to keep it off the edge, leaving nice spacing which is relative to the size of the element's font size.
Then we style list items which have a dark green border around them apart from the bottom, light green background which matches the colour of the lowest pixel in our gradient to create seamless transition, controlled font-size, and are separated from each other by 1 pixel. One more thing is a padding of 1 from left and right to enable the highlights (which we have on the gradient for the button).
And finally we style the <a> container which holds the text of the link. Add the padding (note that for active state button the padding value will be 1 heigher to compensate ovelapping). Remove text-decoration and add the gradient background which is repeated along x-axis and positioned at top left corner.
Next, selected item. To create an active state through selection of elements ids. The procedure is similar to explained above, we set the background of list item to the colour of highlight (lowest pixel) and replace the background of active element with the a corresponing image, adding 1 to padding as explained above.
#tab-nav li#nav-sec1 { background: #fff }
#tab-nav #nav-sec1 a {
background: #fff url(act-tab.png) repeat-x;
padding-bottom: 6px;
color: #000;
}
Sub sections
Finally, we add markup for sub sections:
<div id="tab-subnav">
<ul>
<li id="sub-sec1"><a href="#">Sub Section 1</a></li>
<li id="sub-sec2"><a href="#">Sub Section 2</a></li>
<li id="sub-sec2"><a href="#">Sub Section 3</a></li>
<li id="sub-sec3"><a href="#">Sub Section 4</a></li>
</ul>
</div>
Note that we wrap it around yet another div to make sure IE renders it properly.
We style subsections menu. float it to the right, and apply padding to keep it off the edge of the viewport, aligned to the rest of the lists.
List items are also styled with resized font-size, added padding to separate individual items and adding a divider (border-left). The first item is borderless due to a previous declaration #tab-subnav ul #sub-sec1 {border: none}.
#tab-subnav ul {
float: right;
padding: 5px 5px 0 0;
}
#tab-subnav ul li {
font: bold 75% arial, sans-serif;
padding: 0 7px;
border-left: 1px solid #999;
}
Final result
The final result works and scales correctly across most standards compliant browsers.
This entry has been viewed 4952 times.
Like it? Link to it Del.icio.us it Print it
