content | menu

Internet Styleguide

XHTML+CSS+PHP

Your browser must implement CSS to properly display the demonstrations on this page.

How does it look? Send feedback on the rollover menu example and the overall layout of this page to brian[at]ecoculture[dot]com. Please include OS, browser version, and screen resolution. Confirmation received that the rollover menu works on Windows in Opera 5.12 & 6.0, Netscape 6.2, Mozilla 0.9.9, and Internet Explorer 5.0, 5.5 & 6.0; on Macintosh in Opera 5, Mozilla 0.9.9, and Internet Explorer 5.1 (possible glitch in IE 5.0); and on Linux in Mozilla 0.9.9 [1]. The rollover effect is not intended to work on Netscape 4.x and other older browsers, but it is designed to degrade to an unordered list for these browsers.

This page is based on an earlier example, which will be removed after we finalize this page.

CSS Rollovers

Move your mouse near a menu item, and the background color changes. Positive reinforcement that you've found a working link. The rollover is a simple and effective way to enhance a menu.

We demonstrate how to design a rollover menu using only CSS and XHTML. No Javascript required [2]. We use relative sizes so that the menu's display will adjust to both the user's screen size and preferred font size. The underlying structure of the menu is an unordered list so that it remains meaningful in devices that don't fully use CSS for visual rendering (e.g., older browsers, text-only browsers, screen readers).

Working Model

Here's a working menu that uses rollovers, followed by its style definitions and XHTML markup.

The CSS:

ul.rollmenu {list-style-type: none;
    color: #000;
    background-color: #ffc;
    margin: 0;
    padding: 0;
    border-color: #dda;
    border-style: solid;
    border-width: 1px 1px 0 1px;
    width: 25%;
    voice-family: "\"}\"";
    voice-family: inherit;
    padding: 0 0.5em;
    width: 20%}
    html>body ul.rollmenu {width: 25%}
ul.rollmenu li {font-weight: bold;
    margin: 0;
    padding: 0}
ul.rollmenu ul {list-style-type: none;
    margin: 0.1em 0 0 0;
    padding: 0;
    border-bottom: 1px solid #dda;
    voice-family: "\"}\"";
    voice-family: inherit;
    margin: 0.1em -0.5em 0 -0.5em}
ul.rollmenu a {font-weight: normal;
    text-decoration: none;
    color: #03f;
    background-color: transparent;
    margin 0;
    padding: 0 0.5em 0 1.25em;
    width: 100%;
    border-top: 1px solid #dda;
    display: block;
    voice-family: "\"}\"";
    voice-family: inherit;
    padding-left: 1em}
html>body ul.rollmenu a {width: auto}
ul.rollmenu a:hover {color: #03f;
    background-color: #ff3}

The XHTML:

<ul class="rollmenu">
<li>Group 1
    <ul>
    <li><a href="r/rollovers.html">Link 1:1</a></li>
    <li><a href="r/rollovers.html">Link 1:2</a></li>
    </ul></li>
<li>Group 2
    <ul>
    <li><a href="r/rollovers.html">Link 2:1</a></li>
    <li><a href="r/rollovers.html">Link 2:2</a></li>
    </ul></li>
</ul>

top

Rollover Menu Deconstructed

We work through each line of the style sheet, explaining the effect of the style properties and why some are necessary to overcome inconsistencies among browsers. First, though, here's our menu without any added styling:

The menu above uses the browser's default settings for unordered lists and links. Now, let's see how it gets modified to become our rollover menu.

01  ul.rollmenu {list-style-type: none;

Line 1 begins the style definition for all unordered lists of the class rollmenu. This line also sets the first style property, list-style-type: none, which removes the markers that usually appear before each list item. We apply this property again in line 18 because it is not inherited by nested lists.

02      color: #000;
03      background-color: #ffc;

Line 2 sets the text color, and line 3 sets the background color. These will be used (i.e., inherited) throughout the list, except where we override them. The text color does not apply to links.

04      margin: 0;
05      padding: 0;

The indentation that is characteristic of lists is accomplished with margins or padding. By default, Opera and Internet Explorer set list indentation with margins, and Netscape indents with padding. We set margin to 0 and use padding for indentation because we want to control background colors in the space created by the indent. The 0 value for padding in line 5 is for Internet Explorer version 5.x for Windows (IE5.x/Win), which needs unique settings. In line 12, we'll begin to set other values for padding to affect spacing in other browsers.

06      border-color: #dda;
07      border-style: solid;
08      border-width: 1px 1px 0 1px;

Since this border is applied to the top-level <ul>, it will surround the entire list. The bottom border is left off for now; it will be created in line 21.

09      width: 25%;

This is the first of three settings for the menu's overall width. Multiple settings are necessary because of differences in how browsers, especially Internet Explorer for Windows, implement the CSS box model. The width setting in line 9 id for IE5.x/Win.

10      voice-family: "\"}\"";
11      voice-family: inherit;

Lines 10-11 are the Tantek box-model hack that allows us to override properties within a style definition. IE5.x/Win will stop at line 10 and move to the style definition for the next element (line 15). Most other CSS-aware browsers will continue through the rest of the <ul> style definition.

12      padding: 0 0.5em;

This keeps the group headings away from the side borders. For browsers that don't get fooled by the box-model hack, it overrides the padding: 0 we set in line 5.

13      width: 20%}
14      html>body ul.rollmenu {width: 25%}

The final step for ul.rollmenu is to reset the menu's width for browsers other than IE5.x/Win. Line 13 does this. Then line 14 sets the width again. Why? We're overcoming a problem in IE6.x/Win.

Am I in the box?

In the example above, the text and its dashed, red border are too wide to fit in the black-bordered box. IE6.x/Win expands the black box until the larger box fits inside it. Browsers that implement CSS more correctly leave the black box at its specified size and let the wider line of text flow outside it.

Since we know that IE6.x/Win is going to push the edges of the menu out, we set the width narrower in line 13. Not too narrow, though, or we'll force unnecessary line breaks. Then in line 14, we take advantage of another limitation in IE/Win's CSS implementation — it ignores child selectors (e.g., html>body) — and set the width we want in the most CSS-compliant browsers.

15  ul.rollmenu li {font-weight: bold;
16      margin: 0;
17      padding: 0}

Lines 15-17 make our category headings bold and remove the margin and padding from one layer of the menu.

18  ul.rollmenu ul {list-style-type: none;

Line 18 begins the style definition for our nested list. Each set of links is a <ul> nested under its category heading. Every <ul> needs the declaration list-style-type: none to get rid of all markers throughout the menu.

19      margin: 0.1em 0 0 0;
20      padding: 0;
21      border-bottom: 1px solid #dda;
22      voice-family: "\"}\"";
23      voice-family: inherit;
24      margin: 0.1em -0.5em 0 -0.5em}

The bottom border in line 21 fills in the border left out at line 8, and it provides the line running above the heading "Group 2." The margin settings serve two purposes. The 0.1em top margin lifts the headings off the line running under them. IE5.x/Win gets 0 margin on three sides because it doesn't support negative margins. Browsers making it past the box-model hack get -0.5em margin on the left and right. To understand why, recall that in line 12 we added 0.5em padding to the right and left sides of ul.rollmenu, then read on.

The example above shows a one-item list outlined in solid black, and nested inside it, another one-item list, this one outlined in red dashes with a colored background. The first list has 0.5em padding on the left and right. This ensures that "Heading" doesn't rub against the side borders, but it also creates the 0.5em space on both sides between the red, dashed border and the solid, black one.

The color change that creates the rollover effect only works on the background inside the red, dashed box. If we want the background color to apply to the full width of the menu, we have to widen this box. Negative side margins, as in line 25, do this.

All that's left is to set style properties for the links. This is where we create the rollover effect by using a:hover to change the background color and display: block to cause each link's padding to become part of the link. The default setting for <a> tags is display: inline.

25  ul.rollmenu a {font-weight: normal;

We set font-weight: normal to prevent the links from inheriting the bold applied to the group headings in line 15.

26      text-decoration: none;

Line 26 turns off the underlining that is standard for links. We do this because we think rollovers look better without the underline and to avoid a bug in Opera 6.0. In Opera 6.0 this link will be overlined, rather than underlined:

Opera 6.0 display: block bug

Note that the space between the red, dashed lines is all part of the link. This is the consequence of making the link behave like a block element. If it were an inline element, only the text would be part of the link — not the surrounding padding, too.

27      color: #03f;
28      background-color: transparent;
29      margin 0;
30      padding: 0 0.5em 0 1.25em;

Line 27 sets the color for the link in all its states, i.e., the link always will be blue, whether it has been visited or not. Lines 28 and 29 are precautions in case a browser's default style sheet sets a different value for <a> background-color or margin. The padding keeps the link text from running into the right border and indents the left side of the link so it is inset further than the group heading. The left padding is a little wide for most browsers, but the extra is needed by IE5.x/Win.

31      width: 100%;

IE/Win needs width declarations for most block elements, and for nested blocks like these links, it often needs the width to be specified as 100%.

32      border-top: 1px solid #dda;
33      display: block;

Line 32 adds a separating line above each link. Line 33 is key to making rollovers work; see the example for line 26.

34      voice-family: "\"}\"";
35      voice-family: inherit;
36      padding-left: 1em}
37  html>body ul.rollmenu a {width: auto}

In line 36, we reset the left padding to override the value in line 30. Then in line 37, we let browsers that implement CSS well adjust the width of the links, overriding line 31.

38  ul.rollmenu a:hover {color: #03f;
39      background-color: #ff3}

Finally, we set the background color that we want to appear when someone moves their mouse over the link.

top

Derivations

top

[1] Thanks to several members of the Practical CSS discussion list for browser checks and suggestions for this article, especially Big John, Steve Nelson, and Philippe Wittenbergh.

[2] From at least 1997, Javascript was the dominant language for creating rollover-styled menus. King, A. (2002, March 11). The evolution of rollovers. WebReference Update Newsletter. Retrieved March 30, 2002, from http://www.webreference.com/new/020311.html#feature.