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. 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.

Advanced Navigation With CSS: Horizontal Reverse-Focus

css / navigation

Estimated reading time: 3 minutes, 19 seconds

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:

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 , which is much the same as our previous examples:

<nav role=navigation>
<ul>
<li><a href="#"><span>Start Here</span>Home</a>
<li><a href="#"><span>Our Story</span>About Us</a>
<li><a href="#"><span>Where We Started</span>Graphic Design</a>
<li><a href="#"><span>Our Passion</span>Web Design</a>
</ul>
</nav>

Basic CSS

nav[role="navigation"] { background-color: #666; }
nav[role="navigation"] ul li a {
color: #fff; text-decoration: none;
font-weight: 900; 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 .

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

nav[role="navigation"] li a span {
font-size: x-small; font-weight: 400;
color: #999; 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[role="navigation"] li a

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

nav[role="navigation"] li {
text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3);
}

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

nav[role="navigation"] li a span {
font-size: x-small; font-weight: 400;
color: #999;  display: block;
text-transform: uppercase;
}

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 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:

nav[role="navigation"]: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 a <nav> element with a role of navigation, 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:

nav[role="navigation"] 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:

nav[role="navigation"] {
background-color: #666; padding-bottom:.5em;
}
nav[role="navigation"]:hover li {
text-shadow: 0 0 6px #fff; opacity: 0.8;
}
nav[role="navigation"] li {
display: inline-block; margin-top: -1em;
text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3);
}
nav[role="navigation"] li:hover {
text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3);
opacity: 1; }
nav[role="navigation"] li a {
color: #fff; text-decoration: none;
font-weight: 900; font-size: larger;
padding:.5em;
}
nav[role="navigation"] li a span {
font-size: x-small; font-weight: 400;
color: #999; display: block;
text-transform: uppercase;
margin-bottom: -5px;
}
Explore the code for this navigation bar 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.