Bulletproof CSS Sliding Doors

This entry was published on 25 March 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:

[iframe /demo/Bulletproof/index.html 550 145]


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

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


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


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. ((Watch a screencast. There are some other methods, such as PNG Quant for Windows, PngThing for Mac etc))

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;


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

[iframe /demo/Bulletproof/index.html 550 145]

Download the demonstration files.


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

Comments are closed.

38 responses to “Bulletproof CSS Sliding Doors

  1. Well, the sliding doors technique simply shows how to make those buttons. What they do and where they point to is upto you.

    This is not a tutorial for making interactive tabs. Try a little Jquery to turn them into tabs.

  2. Yeah, we’ve all had to do our own sliding doors modifications to get it fully working… It’s a pity. It’s nice of you to share the fluff with the rest of the world though! 🙂 I’ll have to compare your stuff with mine as well now…. or… for a new client. 🙂

  3. Nice idea, and makes sense for non-transparent images, but this technique won’t work with transparent images, because the ‘a’ and ‘span’ overlap.

  4. @tommie: Glad it is coming to some use. By the way, I think your site is stunning.

    @Ian: The images do not technically overlap. Read the origanal Sliding Doors article at ALA. I tried this with transparent PNG and it works fine.

  5. Azad: Thanks! 🙂 Keep up this real-world-knowledge posts, it’s nice to see something else besides the more newbie friendly ones found on other more popular sites (smashingmagazine.com, nettuts etc..)

  6. I just tried this with transparent PNGs and it does seem the images overlap and thus this method doesn’t work with transparency. (The original ALA method doesn’t either.)

    I took your demo page and swapped out the link and hover PNGs for a pair with transparent corners. http://client.giraffedesign.com/test/azadcreative-sliding-doors.html

    Note the top left corner is rectangular. I tweaked it a bit so when you hover you can see that the images do indeed overlap. (The top left corner turns yellow.)

  7. Thanks Forrest. I have updated the post with a solution to the problem. It does require twice as many images but it is solid and works everywhere.

  8. Unfortunately the demo breaks when the font size is increased. Increasing by one level in Firefox (3.0.10, if it matters) separates the tabs from the white page area below them; increasing by two levels breaks the “Products and Services” image; and so on.

  9. Question. Have you ever tried adding a down effect using :active ?
    I tried what is shown on the link below.
    It works great but it has a problem on IE8. I know IE8 sucks but I kinda need some help resolving this.
    Give it a try on FF and see how it works as it should there. On IE8 it does not respond when you press on it, actually it you press on the right end of the button you’ll notice how it goes down when you press it. The problem seems to be the tag, that’s where IE8 doesn’t want to respond as it should.

    Thanks in advanced for any help. =)

  10. Very nicely done. If you want to take it one step further (which I plan on doing soon) is to remove the flicker in IE6. You can do that by loading the hover state under it and doing display:none when hovered over to reveal the hover state. Hopefully it can be done with this method since it’s so clean.

  11. I cannot seem to get the hover (swapped images) to work.

    What happens is that the natural state do not line up with the hover state (in fact the image for the hover state is pushed a ways to the right. (additionally the left side hover image; my special shape corner; does not even become placed.)

    Am I suppose to add a Display: block or something to get both the images to align without any issue?


  12. I just used your sliding door solution with transparent images, and it worked like a charm! Thank you so much for posting this; it honestly made my day.

  13. Use Adobe Fireworks to save the PNG-8 images with alpha transparency instead (photoshop can only save with index transparency). Then the semi-transparent pixels will be ignored in IE6.

    This way you only need one image that will work on all browsers, just look slightly jaggy in IE6.

  14. This is a GREAT sliding door technique! Awesome job! I do have a problem though, for some reason my “selected” link isn’t selected. Any help would be appreciated!


  15. When I attempt to look at the demo, my antivirus says that the page contains a trojan: Downloader.JS.Pegel.k

    Please fix.


  16. Well, there is one more problem with the transparency:
    When you switch off graphics, all your tabs are “white on white” and doesn’t look like tabs. But when you set a background color to keep it looking as tabs with images switched off, that background is visible through the transparent areas :/

  17. This was awesome!
    Too cool how you made it tell what page it should show as active, i’m going to have to remember that one lol
    Thanks alot!

  18. I got everything to work except selected. I gave body an id of home and my selected image works for home just fine. I tried doing the same thing with another tab, saving identical page and changing body id to products for the second li. I added css to duplicate the li.home portion, but then they are all selected.

    little help pls

  19. can anyone out there lend a hand. I did this tutorial on a test page and it all worked. I tried to insert it into the header of a page I’m currently working on for a real site. The problem comes when I give the body tag an id to specify the active page. My entire page goes crazy and everything shifts around. I have never used body id before. what is happening there. Do I need to alter other areas of the CSS?


  20. the tutorial being useful, I’m greatly irritated by the “summary” box following me all the way (I am not paranoid I think 😛 and have no ADHD, either). I consider that bad design since I cannot concentrate on the main topic. luckily I can use Chromium Dev Tools to remove it, but you should change that as well (e.g. position: fixed; than it doesn’t _move, at least).

  21. I actually thouroughly enjoyed this point Bulletproof CSS Sliding Doors – Saddam Azad – UI Designer, Front-end Engineer. it was a definite terrific browse through thank you

  22. Hi There! I am trying to do something similar to this. I am essentially creating one large button with an unordered list inside. When you rollover the list items, the background image on the whole button needs to change. I am having an issue directing to the nested div instead of the list item itself. Any help would be greatly appreciated

  23. For those having the problem with the ‘selected’ bit. It is because the links go to another page. In this example he has href=”#” which stays on the same page and doesn’t refresh the javascript. I’m only a beginner so I don’t know how to fix this.