CSS Nav Menu Tricks

Horizontal and vertical menus without cumbersome LI abuse.

Shop for web design and development books here.


In this section, I will attempt to document and demonstrate how to overcome some of the little problems that many developers encounter while transitioning from transitional to strict doctypes.

How to Make Reliable, Friendly Navigation

Designers are always trying to create clever navigation systems—drop-down, slide-out, collapsing, etc—and users are always resenting them for it. I’ve never met a client, nor any web user, who wants to repeatedly chase expanding & collapsing, appearing & disappearing menus with their mouse. So let’s all resent such menus together, and make menus that people like to use.

There is nothing backward, deprecated, nor wrong with a simple horizontal or vertical list of links. Here are some rules that users like:

  • Links should be large enough to read, even if you’re over 50.
  • Links should be easy to point at—padding around links will accomplish this. Don’t you just hate those tiny pagination numbers? Use CSS to put a box around them, with 2-3px of padding—but don’t put a visible box around inline links within paragraphs. It looks tacky, and messes up your line-spacing. Along those lines, also avoid hover effects that make the text line “jiggle,” such as changing border or font-weight on inline links.
  • Links should obviously be links—color, background, and border may be employed to this end. Underlining is a deprecated typewriter-effect, and usually should be avoided.
  • Links should always say what they do and do what they say. Avoid links like, “Click Here.”

Horizontal Menu

Note: Examples of these menus may be seen in the Table Example page.

This menu example will run the width of the fluid page, just under the header table, with decorative effects. The menu bar is inset, has a background, and the links are CSS “buttons” with a mouseover effect using inset/outset border. Notes:

  • Use padding:0 in the td, else it’s background will shift.
  • Who knows why an A in a TD will not obey margin-top of the A, nor vertical-align:middle of the TD? It is necessary to enclose all the links in one P and give that a bit of top margin, to vertically center the link buttons in the cell.
  • Most of the text formatting may be applied to the cell.
  • Use margin (outside) and padding (inside) to make the size, separation, and borders of the links behave as desired.
  • IE will display the buttons a pixel higher than FF.
  • If the links are wrapped (in the HTML code), one extra space will appear between the buttons. Adjust their l/r margins accordingly.
table.lay { /* our usual fluid layout table */
border-collapse:collapse; width:100%; margin:0; border:0; }

#topmenu { /* the td the links are in */
width:100%; height:24px; margin:0; padding:0;
border:#E2DCC7 1px inset;
background:url('img/paper2-24.jpg') repeat-x scroll left top;
font-family:"Century Gothic",futura,"URW Gothic L",sans-serif;
font-size:12px; font-weight:bold; text-align:center; }

#topmenu p { margin:2px 0 0 0; } /* scoot them down a bit */

#topmenu a { /* define the links as buttons */
margin:0 2px 0 2px; padding:0px 5px 1px 5px;
background-color:#F0E8D7; border:#FFFFFF 1px outset;
text-decoration:none; }

/* no need to repeat all that in a pseudo, just the diffs: */
#topmenu a:hover {
border:#FFFFFF 1px inset; background-color:#E2DCC7; }

The HTML to create the menu bar is even simpler. The td’s contents may be strung out on one line, if you prefer, and in fact must be so if you don’t want an extra space between buttons.

<!-- Top menu -->
<table class="lay">
 <td id="topmenu">
  <a href="link1.asp">Link 1</a>
  <a href="link2.asp">Link 2</a>
  <a href="link3.asp">Link 3</a>
<!-- No LI Abuse! -->

Vertical Menu

This is just a little different, in that it uses display:block and sets width on the link buttons, to make them fit the column and look nice. The purpose of the btn class is so we can put other kinds of links in the left column, like an RSS graphic or inline links in the News area.

#lft { /* our usual left-column td def */
border:0; width:175px; min-width:175px; padding:20px;
background-color:transparent; font-size:0.9em;}

#lft a.btn {
display:block; width:100%; text-align:center;
text-decoration:none; font-weight:bold;
font-family:"Century Gothic",futura,"URW Gothic L",sans-serif;
border:1px outset #E2DCC7; background:#F0E8D7;
margin:0 0 5px 0; padding:1px 2px 2px 2px; }

#lft a.btn:hover {
border:1px inset #E2DCC7; background:#E2DCC7; }

The HTML is even simpler than the last example, because, being in the existing left column of the existing content table, all we need is an optional heading, and the links. Also, we don’t need to contain the anchors in a P, UL/LI, or any other tag, because they are display:block elements and will arrange themselves vertically.

<!-- within our left td -->
<h1>CSS Menu</h1>
<a class="btn" href="link1.asp">Link 1</a>
<a class="btn" href="link2.asp">Link 2</a>
<a class="btn" href="link3.asp">Link 3</a>

So there you have it. Once again, there is no messy, deprecated table markup, and (even better) no messy, fussy, floated DIVs, ULs, or LIs. Use the third alternative: CSS-controlled tables. They just work!

Leave a Reply

Your email address will not be published. Required fields are marked *