Menu Tutorial

Pre 2006

How to code and style a single level html/css menu. See the 'Information' section below.


I can't press this point too hard - when you are FIRST starting out with css DON'T USE LISTS unless you have a real need to do so.

I know that some sites say that this is the correct way to produce your navigation buttons and proceed to show how it works. But it is far too complicated, leads to bloated xhtml AND bloated CSS. Finally with all this extra coding there is so much to go wrong. If accessibility is an issue then there are other ways and another type of list that I believe is more suitable.

LINKS are not LISTS as such. You can put your navigation links into a list if you want to make use of the list features, bullets and indent. But why put your LINKS into a LIST only to remove the bullet AND remove the indent?

There, I've said my piece, so on to 'my way' for vertical and horizontal menus without lists.

A Vertical Button Menu - The EASY Way

First create your links in html and for this example I will put the links straight into the body without a containing div just to show how simple it can be.


<a class="nav" href="page1.html" title="page 1">Page 1</a>
<a class="nav" href="page2.html" title="page 2">Page 2</a>
<a class="nav" href="page3.html" title="page 3">Page 3</a>
<a class="nav" href="page4.html" title="page 4">Page 4</a>
<a class="nav" href="page5.html" title="page 5">Page 5</a>

Example 1

Not much of a button menu, but that is ALL the XHTML you will need! The class="nav" is not absolutely necessary but I find that it saves a lot of hassle if you asign a class to the link rather than any containing div.

ok, the (x)html is done, so on to the CSS.

Firstly let us set up the size of the menu button:
This is done by using display:block; with width and height values.

a.nav, a.nav:link, a.nav:visited {display:block; width:150px; height:25px;}

Example 2

now to make it look like a button we can add a border and a background-color:

a.nav, a.nav:link, a.nav:visited {display:block; width:150px; height:25px; background:#dca; border:1px solid #000;}

Example 3

Let's show these buttons with a little separation and do something about the text:

a.nav, a.nav:link, a.nav:visited {display:block; width:150px; height:25px; background:#dca; border:1px solid #000; margin-top:2px; text-align:center; text-decoration:none; font-family:verdana, arial, sans-serif; font-size:12px; color:#000;}


Use margin-top not margin-bottom as this can cause problems 'further down the line' in Opera.

Example 4

Almost there, just move the text down to the vertical center and we have our basic button

a.nav, a.nav:link, a.nav:visited {display:block; width:150px; height:25px; background:#dca; border:1px solid #000; margin-top:2px; text-align:center; text-decoration:none; font-family:verdana, arial, sans-serif; font-size:12px; color:#000; line-height:25px; overflow:hidden;}


Add overflow:hidden for IE if the text is large enough to cause IE to increase the vertical height of the button.

Example 5

Ok, now for the dynamic bit to produce the hover and active states of the button. First we define the differences required for :hover

a.nav:hover {color:#fff; background:#764;}

Example 6

and finally the :active state.

a.nav:active {color:#fff; background:#c00;}

Example 7

Now compare the CSS required for this method to that required by the 'list' method.

one more pointer.

If you need to show one of the menu items as being active then just add a span class using the same css as the a.nav and a.nav:active and use this for your active 'link'.

The same dynamic button menu with 'page 2' selected:

Example 8


That's it, the vertical menu 'done and dusted'.

So now to tackle the horizontal menu.

You would expect this to be more complicated if you have been using lists but not a bit of it, it is EXACTLY the same as the VERTICAL menu, with just one necessary addition to the CSS.

JUST add float:left; to the a.nav, a.nav:link, a.nav:visited. (with a right-margin if you want separation).

It would have been nice to be able to use display:inline-block; but this is not supported in all browsers

The HORIZONTAL button menu:

Example 9


And there you have it, no complicated css structure to deal with .div .ul .li, just plain simple css directly styling the link. If you want to place your menu in a specific position you could use a container div and position this either relative or absolute, but it works equally as well in the normal flow of your page.

Just one point to watch out for and that is, because the horizontal menu uses floats you may need to use clear:both; to continue the page flow correctly.


Should this be an issue in your layouts then there are easy ways to produce some formatting into your text-only browsers.


At the moment your vertical buttons will appear as a line of links in text-only browsers. To produce a vertical set of links just enclose your links in a div and add <br /> enclosed in a span at the end of each link so that your (x)html becomes :

<div id="nav">
<a class="nav" href="page1.html" title="page 1">Page 1</a><span><br /></span>
<a class="nav" href="page2.html" title="page 2">Page 2</a><span><br /></span>
<a class="nav" href="page3.html" title="page 3">Page 3</a><span><br /></span>
<a class="nav" href="page4.html" title="page 4">Page 4</a><span><br /></span>
<a class="nav" href="page5.html" title="page 5">Page 5</a><span><br /></span>

and in your css add :

#nav span {display:none;}

In a text-only browser your links will now appear as :
Page 1
Page 2
Page 3
Page 4
Page 5

Horizontal Links

If you wish your text only browser to show your links on the same line it is advisable to put them into square brackets to give a clear separation between them. This can be achieved using the same method as for vertical links. Place your links in a div and surround each link with a square bracket enclosed in a span:

<div id="nav">
<span>[</span><a class="nav" href="page1.html" title="page 1">Page 1</a><span>] </span>
<span>[</span><a class="nav" href="page2.html" title="page 2">Page 2</a><span>] </span>
<span>[</span><a class="nav" href="page3.html" title="page 3">Page 3</a><span>] </span>
<span>[</span><a class="nav" href="page4.html" title="page 4">Page 4</a><span>] </span>
<span>[</span><a class="nav" href="page5.html" title="page 5">Page 5</a><span>] </span>

and again, in your css add :

#nav span {display:none;}

In a text-only browser your links will now appear as :
[Page 1] [Page 2] [Page 3] [Page 4] [Page 5]


There are a couple more list types available other than the unordered list that most people favour. For this last method I will use DEFINITION lists.

These are similar in structure to unordered and ordered lists and are opened using <dl> and each item in the list is enclosed in <dt>.....</dt> with a final </dl> to close the list.

The benefit of using this type of list is that you do not need to use CSS to style the definition list. It can safely be ignored and, as with my first method, just style the links.

<dt><a class="nav" href="page1.html" title="page 1">Page 1</a></dt>
<dd>An expanded definition of page 1 link</dd>
<dt><a class="nav" href="page2.html" title="page 2">Page 2</a></dt>
<dd>An expanded definition of page 2 link</dd>
<dt><a class="nav" href="page3.html" title="page 3">Page 3</a></dt>
<dd>An expanded definition of page 3 link</dd>
<dt><a class="nav" href="page4.html" title="page 4">Page 4</a></dt>
<dd>An expanded definition of page 4 link</dd>
<dt><a class="nav" href="page5.html" title="page 5">Page 5</a></dt>
<dd>An expanded definition of page 5 link</dd>

In a text-only browser your links will now appear as :

Page 1
An expanded definition of page 1 link
Page 2
An expanded definition of page 2 link
Page 3
An expanded definition of page 3 link
Page 4
An expanded definition of page 4 link
Page 5
An expanded definition of page 5 link

What is more, definition lists allow you to add a 'definition' to each item using <dd>...</dd> around the definition as demonstrated above, so you could use this feature to define the function of each link. Using CSS you could set this to display:none; for normal button links but, as shown above, in a text-only browser this would be displayed and give added information to people browsing your site.

If you want vertical links then the CSS as my first example will work. If you want horizontal links then just add float:left; as in my second example.


For examples of definition lists and how to style them see the appropriate menu links.


You may use this method on your personal 'non-profit' web site without seeking my permission. A link back to CSSplay is always appreciated.

Commercial usage is also permitted without seeking approval, but I would ask that a donation is considered to support my work on CSSPlay.

If you are having problems integrating any of my demonstrations into your website then I now offer a service to fault find and correct any errors that you may have introduced. Please email me for more information.

Please Support CSS play

Please note that if your donation is for a demo/menu then you will need to email me with the url of the demo/menu after making the donation

For more CSS demonstrations I recommend that you visit the Dynamic Drive CSS Library.

Free, practical CSS menus, layouts, and examples

Soft Geometry Creative Industries

Soft Geometry Creative Industries
is a music-based design company located in Bristol UK.
I create artwork for albums, singles, posters and t-shirts.
My work is influenced by punk and post-punk poster and flyer design,
lo-fi photocopy aesthetics,
Francis Bacon and Mark Rothko.

I can provide a start to finish service with my own art and photography, put together work from images provided by yourself, and collaborate on an idea.

Follow CSS play

Facebook   Twitter   Facebook Fan Page