demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my projects

CSSslidy: an auto-generated #RWD image slider. 1.5K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Remora: a CSS-only dropdown menu

css / navigation

Estimated reading time: 3 minutes, 22 seconds

Horizontal “drop down” menus for are familiar to almost every web user, so they are a natural fit for sites that have many pages organized into seven or fewer categories.

Many web developers assume that creating a drop down menu requires ; the reality is that the menu system is merely a nested HTML list, just like those we have created in the past, with the presentation handled by , no JavaScript required.

It should be noted that there are many, many CSS drop down menus out there. The most well-regarded is the “Suckerfish” code, originally developed in an article on A List Apart. The system I am about to describe is an evolution of the ideas expressed in that article, with less vestigial code and fewer concessions to older browsers: thus, “Remora”.

First, the code. Once again, we are using nested lists; as before, you should be careful to ensure that any new lists are contained inside an <li> element with a class of submenu. Each nested list will be a drop-down menu element.

As I am currently residing in Auckland, I will make the drop down menu for a fictional boat-building website:

<ul id="nav">
<li class="submenu"><a href="#">Yacht designs</a>
<ul>
<li><a href="#">Sloops</a>
<li><a href="#">Ketches</a>
<li><a href="#">Yawls</a>
<li><a href="#">Schooners</a>
</ul>
<li class="submenu"><a href=#>Small boat designs</a>
<ul>
<li><a href="#">Skiffs</a>
<li><a href="#">Tenders</a>
<li><a href="#">Dories</a>
<li><a href="#">Canoes</a>
<li><a href="#">Kayaks</a>
</ul>
<li class="submenu"><a href="#">Clippers</a>
</ul>

(Note that every entry on the main navigation bar will require a class of submenu, even if it does not contain an actual menu).

Now the CSS. First, we will reset both the list and links, removing all spacing, text decoration and bullets, while specifying a new font. At the same time, we’ll specify that each link in the list will always display on its own line; by doing so, we can also give links a set width:

ul#nav, ul#nav ul { padding: 0; margin: 0; list-style-type: none; }
ul#nav a { text-decoration: none; color: #fff; background: #000;
font-family: Eurostile, "Square 721", Arial, sans-serif;
display: block; width: 10em; padding: .2em; }

This makes the entire navigation vertical, like our accordion menu example. We want the main <li> elements, the one with a class of subnav, to appear beside each other. We could try display: inline, but that would remove any opportunity to provide them with a width, in the event that we wanted to push the main menu items further apart. Instead, we’ll float them:

ul#nav li.submenu { float: left; position: relative; }

Note that this will effectively float the entire menu; if you want the menu bar to appear on its own line, there are two possible solutions:

  1. Keep the menu bar at its current length and height and set clear: left on the first element that follows it, be it a heading or paragraph.

  2. Set a height of 1.8em or so to the ul#nav list and add an appropriate background colour. The main unordered list is not floated – it just doesn’t have any height, and therefore does not push around other elements.

  3. To create the “drop-down” effect we need to visually remove the submenu lists from the page. While there are many possibilities for achieving this, the tried-and-true method is to position the submenu lists absolutely, and then to give each list a left position that is far off the screen (we can’t use right, as can never anticipate just how wide a browser might be). When the user hovers their mouse over the parent <li>, we reset that distance to 0:

ul#nav li ul { position: absolute; left: -999em; }
ul#nav li:hover ul { left: 0; }

That’s it. I would typically add a little more CSS to make the menus look better, (as you can see in the example above), but the functionality is entirely there.

One final note: it is poor form (not to mention potentially confusing to users) to obscure important information with a drop-down menu. You have a few choices: either apply sufficient margin-bottom to the menu (at least equal to the height of the tallest drop-down element) to push other content out of the way, or apply opacity or rgba values to the drop-downs themselves.

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.