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 other blogs

Massive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K 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 I have feature here in the past, with the presentation handled by , no JavaScript required.

It should be noted that there are many, many CSS drop down menus available. The most well-regarded is “Suckerfish” code, originally developed 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. Since I am using nested lists, you should be careful to ensure that any new lists are contained insidean <li> element.

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

<li><a href="#">Yacht designs</a>
<li><a href="#">Sloops</a>
<li><a href="#">Ketches</a>
<li><a href="#">Yawls</a>
<li><a href="#">Schooners</a>
<li><a href=#>Small boat designs</a>
<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>
<li><a href="#">Clippers</a>

Now the CSS. First, we will mini-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:

nav ul {
padding: 0; margin: 0;
list-style-type: none;
font-size: 1.4rem;
nav ul a {
text-decoration: none;
color: #fff;
background: rgba(0,0,0,0.8);
font-family: Eurostile, "Square 721", Arial, sans-serif;
display: block; width: 10em;
padding: .4em;
transition: .3s;

This makes the entire navigation vertical, like the accordion menu example. We want the main <li> elements 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. inline-block and <flex> have downsides too, in this case, so we’ll float the elements:

nav ul > li { float: left; position: relative; }

Note the use of the immediate child combinator.

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, I'll position the submenus absolutely, and then give each submenu a value of 0 for opacity. When the user hovers their mouse over the parent <li>, I'll reset the opacity to 1. I'll also add a :focus state to capture older mobile browsers:

nav ul li ul {
position: absolute;
opacity: 0;
transition: .4s;
nav ul li:hover ul { opacity: 1; }

You'll find one small issue: you can activate the submeus by moving your mouse over the area where the submenus lie on the screen, because they are still “there”, suppounded by their parent <li> elements, just not visible. At the same time, the drop-down system won't work on older mobile browsers, which have no concept of “hover”. To fix both of these issues, the CSS we've just written is adjusted to:

nav ul li ul {
position: absolute;
opacity: 0;
transition: .4s;
pointer-events: none;
nav ul li:hover ul, nav ul li:focus ul {
opacity: 1; pointer-events: auto;

That’s it!. The system could be further improved by @media queries for smaller screen sizes, but I'll leave that for other articles on this blog, and the CodePen repo linked below.

Photograph by Ilya Fedorov, licensed under Creative Commons. Play with the code for the Remora system on CodePen

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.