Bulletproof CSS Sliding Doors

This entry was published on March 25, 2009 and may be out of date.

I have had to build a few sliding doors navigation menus in the last few weeks. I did a quick research and browsed though a few different implementations. To be perfectly honest, I found none of them satisfactory for various reasons. So I decided to crack the nut myself.

The solution may not be perfect for every purpose but it does overcome most of the shortcomings of the existing techniques.

What we are making

Without further ado, let me introduce you to the Bulletproof CSS Sliding Doors menu, basic edition:

Problem with existing implementations

1. Not fully click-able
Douglas Bowman’s original CSS Sliding doors only has one problem. There are 9 dead pixels to the left of every button. I wanted the entire button to be clickable.

2. Uses empty <span> tags
Although it is perfectly valid to have empty spans, I would rather not take this approach. I would like my markup to make sense to future developers.

3. Causes inconsistencies in IE6
Kailoon’s One Image solution works perfectly. This is perhaps the most compatible solution there is. But there is a slight rendering issue in IE6. There is an extra bit of padding to the left of  each button. Off course, it can be fixed easily with a little Conditional CSS but it is not the ideal solution.

Also, kailoon adds a 4px padding to the anchors and then uses -4px margin on the <span> to cover it up. Although this mechanism works well, I am not a big fan of negative margins.

It is completely your prerogative to decide whether or not you would support Internet Explorer 6. You may choose this solution if IE6 is no longer an issue.

4. Breaks when font-size is increased
The most common with most of these implementation is that they cannot cope with increased font-sizes.

5. Uses li:hover which does not work in older browsers
The :hover pseudo-class is not supported by IE6 and below when applied to anything but an anchor. Hence, Stu Nicholls’ 100% Clickable Sliding Doors does not function as expected on older browsers. Otherwise, I really like his solution.

The solution

I have designed a simple layout design in Photoshop for the menu we are about to make.

Download the PSD.

The Exported Images

Since we are using transparent PNGs for the buttons, you will notice that the images will overlap. If your images have shadows, the overlap will cause rather ugly results.

The solution is to split the images into 2 sections. What you get is 2 images, one for each slice as demonstrated above.

If you want to create CSS Sprites at this point, feel free to do so (with this excellent guide from Alistapart). I do not think I need to take the time to show how to do this since this topic has been very well covered by so many publications.

The Markup

<div id="navigation">
  <ul>
    <li><a href="#"><span>Homepage</span></a></li>
    <li><a href="#"><span>Products &amp;amp;amp; Services</span></a></li>
    <li><a href="#"><span>Contact Us</span></a></li>
  </ul>
</div>

This is a simple unordered list enclosed in a div. The list items contain anchors which in turn contains a span encompassing the text.

The CSS

First off, I will add some basic styling.

.navigation {
  background: url(images/navigation.png) top left repeat-x;
  height: 134px;
  overflow: auto;
  display: block;
  float: left;
  width: 100%;
}
.navigation * {
  padding:0;
  margin:0;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  text-transform: uppercase;
}
.navigation ul {
  display: block;
  float: left;
  padding: 10px 0 0 0;
  margin: 37px 0 0 20px;
}
.navigation ul li {
  list-style: none;
  float: left;
  margin: 0 0 0 5px;
}

What I have done here is:

  • Add blue background to the entire navigation. You can ignore most of it since it is meant only for the menu I designed. Keep the overflow: auto for clearing the floating unordered list.
  • Resetting everything inside #navigation using the very powerful star (*) selector, so they have no margin and padding and so that they inherit the font properties. If you have already used a CSS Reset in your master stylesheet, ignore this bit of code.
  • Remove list-style from list items and make them float left.

The CSS for links

.navigation ul li a {
  background: url(images/nav_right.png) top right no-repeat;
  display: block;
  padding: 0 13px 0 0;
  color: #578ba0;
  text-decoration: none
}
.navigation ul li.selected a,
.navigation ul li.hover a {
  background: url(images/nav_selected_right.png) top right no-repeat;
  color: #578ba0;
}

.navigation ul li a span {
  background: url(images/nav_left.png) top left no-repeat;
  display: block;
  padding: 15px 10px 10px 23px;
}
.navigation ul li.selected a span,
.navigation ul li.hover a span {
  background: url(images/nav_selected_left.png) top left no-repeat;
}

The code here is quite self explanatory. The image nav_selected_right.png and nav_selected_left.png are applied to anchor and span respectively for the hover effect as well as for highlighting selected items.

Compatibility

The images used in this demo use alpha-transparency for shadows which are, off course, not supported by everyone’s favourite browser: Internet Explorer 6.

Take the following steps only if you intend to support IE6.

1. Export alpha-transparent PNG-8 images from Fireworks.1

2. Make some changes to the CSS

.navigation ul li a {
  background: url(images/nav_right_IE6.png) top right no-repeat !important;
  background: url(images/nav_right.png) top right no-repeat;
  display: block;
  padding: 0 13px 0 0;
  color: #578ba0;
  text-decoration: none
}
.navigation ul li.selected a,
.navigation ul li.hover a {
  background: url(images/nav_selected_right.png) top right no-repeat !important;
  background: url(images/nav_selected_right_IE6.png) top right no-repeat;
  color: #578ba0;
}

.navigation ul li a span {
  background: url(images/nav_left.png) top left no-repeat !important;
  background: url(images/nav_left_IE6.png) top left no-repeat;
  display: block;
  padding: 15px 10px 10px 23px;
}
.navigation ul li.selected a span,
.navigation ul li.hover a span {
  background: url(images/nav_selected_left.png) top left no-repeat !important;
  background: url(images/nav_selected_left_IE6.png) top left no-repeat;
}

Demo

Here is the final demonstration, once again, for your convenience:

Download the demonstration files.

Conclusion

In comparison to other methods, it is more functional, semantic and better supported in older browsers. It is also easier to deploy and maintain.

I hope you found it useful. Bugs, fixes and any feedback is very welcome.

References and Credits

CSS Sliding Doors by Douglas Bowman

CSS Sliding Door using only 1 image by kailoon

100% clickable Sliding Doors by Stu Nicholls

Sliding Doors meets CSS Sprites by FiftyFourEleven

  1. Watch a screencast. There are some other methods, such as PNG Quant for Windows, PngThing for Mac etc []