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.

featured articles

popular favourites

Advanced Navigation With CSS: Horizontal Reverse-Focus

While searching the web for inspirational navigation ideas to share with my classes, I came across this example at 3point7designs. While it is labeled as an "advanced CSS navigation bar", the reality is that the tutorial uses images and a well-established technique (CSS Sprites) to provide an effect. Looking at it, I realized that the menu bar could be created entirely in CSS, with no images required, via the addition of a little CSS3:

From a UI perspective, the navigational construct is interesting: rather than highlighting the user's selection, it blurs out options that are not chosen, leaving the selection in focus. Implemented poorly, this would be the definition of "mystery meat" navigation, but the UI rescued by the fact that the entire navigation bar is in focus when the user's mouse is outside its immediate vicinity, allowing the user to clearly see all the navigational options.

Markup

First, let's establish the basic HTML markup, which is much the same as our previous examples:

  1. <ul id=nav">
  2. <li><a href="#">Home</a></li>
  3. <li><a href="#">About Us</a></li>
  4. <li><a href="#">Graphic Design</a></li>
  5. <li><a href="#">Web Design</a></li>
  6. </ul>

CSS

  1. ul#nav { background-color: #666;
  2. font-family:"Century Gothic", Verdana, Arial, Helvetica, sans-serif; }
  3. ul#nav li a { colour: #fff; text-decoration: none; font-weight: 900;
  4. font-size: larger; padding:.5em; }

The markup is complicated by the fact that there are sub-headings above each navigational element. The sub-headings require extra markup to be wrapped around them in order to be treated separately via CSS; the only question is what markup to use:

  • You could change the markup to a definition list and place the links inside <dt> tags, and the subheadings inside <dd> elements. There would be a small issue in that you'd need to reverse their order of appearance for the menu bar: in this case, the <dd> content would appear above the associated terms. It's certainly possible with CSS, but could be a little tricky.

  • You could pace the subheading text inside some lower-importance element, such as a <h5>
  • You could wrap the sub-heading text with <sup>
  • Finally, you could use span

If we stick with <span>, our content and markup would become:

  1. <ul id=nav">
  2. <li><a href="#"><span>Start Here</span>Home</a></li>
  3. <li><a href="#"><span>Our Story</span>About Us</a></li>
  4. <li><a href="#"><span>Where We Started</span>Graphic Design</a></li>
  5. <li><a href="#"><span>Our Passion</span>Web Design</a></li>
  6. </ul>

Then we need to treat the text inside the <span> with CSS:

  1. ul#nav li a span { font-size: x-small; font-weight: 400; colour: #999;
  2. text-transform: uppercase; }

(Note that we need to alter font-weight for the <span> text, as it will otherwise inherit font-weight from the style applied to ul#nav li a )

drop-shadow

All of the text in the nab bar requires a subtle drop shadow. We will use the CSS3 property text-shadow to create this:

  1. ul#nav li { text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3); }

Then we make the text inside <span> display: block, so that it appears on a separate line:

  1. ul#nav li a span { font-size: x-small; font-weight: 400; colour: #999;
  2. display: block; text-transform: uppercase; }

Now we have a layout issue we need to fix: we want each list item to be side-by-side. There are two solutions to this:

  1. Float the list item elements left. This will cause the ordered list element to collapse: its computed height will be 0, as the height of container elements do not take into account elements floated inside them. This could be fixed by using a variation of the float-flag fix.

  2. Give the list item elements a display value of inline-block. The downside to this technique is that older versions of Internet Explorer to not understand inline-block

I will use the second solution for this example. In either case, you will probably find that you need to move the span text closer to the other text in the link by using a combination of negative margin and reduced line-height.

:hover on everything

The technique that allows the "reverse-focus" effect to work in the original 3point7design article is the same for this example: the fact that :hover can be used on everything. Traditionally, most developers think of :hover as a pseudo-class that can only be applied to <a> elements, in part because that's all IE6 supported; in reality, :hover can be applied to any element at all.

First, we need to "blur out" all the text in the navigation bar when the user's mouse is anywhere near it:

  1. ul#nav:hover li { text-shadow: 0 0 6px #fff; opacity: 0.8; }

The selector for this declaration could be phrased as "when the mouse is over an unordered list with an id of "nab", do what follows to the <li> elements inside it".

The declaration replaces the text-shadow on <li> content with a white shadow that is not displaced horizontally or vertically, but has a significant amount of blur. At the same time, the opacity of the <li> element is reduced by 20%.

(This same technique can be used to created "glow" effects around text. Please don't do this.)

Now we have to reverse the blur effect for the specific list item that the user's mouse happens to be over:

  1. ul#nav li:hover { text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3); opacity: 1; }

That's all you need: six condensed lines of CSS, that could probably reduced to five with a little work.

The entire stylesheet:

  1. ul#nav {
  2. background-color: #666;
  3. font-family:"Century Gothic",Verdana,Arial,Helvetica,sans-serif;
  4. padding-bottom:.5em; }
  5. ul#nav:hover li { text-shadow: 0 0 6px #fff; opacity: 0.8; }
  6. ul#nav li { display: inline-block; margin-top: -1em;
  7. text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3); }
  8. ul#nav li:hover { text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3); opacity: 1; }
  9. ul#nav li a { color: #fff; text-decoration: none;
  10. font-weight: 900; font-size: larger; padding:.5em; }
  11. ul#nav li a span {
  12. font-size: x-small; font-weight: 400; colour: #999;
  13. display: block; text-transform: uppercase; margin-bottom: -5px; }

You must be signed up in order to leave comments.

web developer guide

featured comment

by Aisling Brock in New Business Card Design

what i'm reading

A Feast for Crows: A Song of Ice and Fire: Book Four
A Feast for Crows: A Song of Ice and Fire: Book Four

what i'm watching

Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy]
Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy]

what i'm playing

Borderlands
Borderlands

what i'm hearing

Planets
Planets

blogs

podcasts

no ads ever

This blog is free of advertising, and always will be.

creative commons licensed

The content of this blog is free to use in whatever way you wish under the Creative Commons license.