Image Based SEO-Friendly CSS Menus... That Work

By Jim McFadyen, Web Developer

The Issue

Your CSS-based menu uses background images that you swap on rollover events. In Internet Explorer, you'll notice an annoying flicker effect (and/or hourglass cursor) when you rollover elements within the menu.

This is because in IE6, the browser decides to do us a "favour" and request a new background image every rollover event. (Thanks, Microsoft.) This issue becomes more evident when the menu includes drop downs.

The method presented here eliminates the flicker as only one image is swapped in and out.

This document will not get into the JavaScript required to implement a CSS menu in IE. Just know that there is an -over state declared for each menu element in the CSS that instantiates itself and executes on a rollover event.

The Solution

As an obvious starting point, it is understood that we want our XHTML menus to follow web standards. To that mix, we add the other requirements that include accessibility, search engine optimization, and of course, anti-aliased text with different coloured backgrounds on rollover.

  <ul id="nav">
    <li class="nav" id="nav0"><a href="link.html"><span>My Favourite Pirates</span></a></li>
    <li class="nav" id="nav1"><a href="link2.html"><span>Backcountry Skiing</span></a></li>
    <li class="nav" id="nav2"><a href="link3.html"><span>Search Engine Optimization</span></a></li>
  </ul>

Above is semantic web standards compliant code. It is accessible and search engine friendly (having keywords for text links). Admittedly, there is the extra, apparently useless <span>, but that is one of the most important elements as far as accessibility and SEO are concerned. The only thing that this clean XHTML is lacking is what many would consider the most important: a slick presentation.

Here's the trick: we cannot have a background image on the rollover state, or we will get flicker and/or an hourglass cursor.

Instead, we create a single image with all of the rollover states and place it as the background image of the <div id="nav"> element. Now when we rollover each of the menu items, we simply turn off the background image and use a transparent background definition. Simple. Here is the CSS:

#nav{width:760px;height:30px; background:#fff url(/rollover-nav.gif) no-repeat;}
#nav{position:relative;}
#nav li{display:inline;}
#nav li a{display:block;}
#nav li a span{display:none;}
.nav,.nav-over{position:absolute;height:30px;}
.nav a,.nav-over a{height:30px;}
#nav0{left:0px;background-image: url(pirates.gif);}
#nav1{left:87px;background-image: url(skiing.gif);}
#nav2{left:182px;background-image: url(seo.gif);}
#nav0:hover,#nav-here,#nav0-over,##nav0-here,##nav-here-over{left:0px;background:transparent;}
#nav1:hover,#nav-here,#nav1-over,##nav1-here,##nav-here-over{left:100px;background:transparent;}
#nav2:hover,#nav-here,#nav2-over,##nav2-here,##nav-here-over{left:200px;background:transparent;}

As we can tell from the CSS, the <span> elements are not displayed because the inner text is of no use to the presentation (we're using images, remember). It is simply XHTML content for use with assistive devices and search engine spiders. Each element in the menu is absolutely positioned, since the widths of each element might differ with the image used for each menu item. It will also make our lives easier for when we need to add a drop-down menu - now a trivial exercise!

This is a very simple, clean solution to have your users see the presentation as design envisioned. It adheres to web standards, allows assistive devices easy access, and search engines can make use of valuable keywords linking to pages.