Sliding Doors of CSS, Part II

A note from the editors: While brilliant for its time, this article no longer reflects modern best practices.

Sliding Doors of CSS (Part I) introduced a new technique for creating visually stunning interface elements with simple, text-based, semantic markup. In Part II, we’ll push the technique even further. If you haven’t read Part I yet, you should read it now.

Article Continues Below

Here, we’ll cover a new scenario where no tab is highlighted, combine Sliding Doors with a single-image rollover, provide a fix for the clickable region in IE/Win, and suggest an alternate method of targeting tabs. We’ll skip a basic recap of the technique (see Part I for this) in favor of jumping right back in where we left off.

No Current Tab#section1

In Part I, we didn’t account for cases where there might not be a “current” tab that gets highlighted. For example, a registration process, or pages containing legal text, might not fit under any of the sections represented by tabs. If none of the tabs are styled as the “current” tab, the rule which adds an additional 1 pixel of bottom padding won’t get used. Thus, the tabs end up obscuring the rule running along the tabs’ bottom edge.

Adding a bottom border of 1px to all “non-current” tabs, then removing the bottom border in case of an existing “current” tab, provides an easy fix:

#header li {
  float:left;
  background:url("left.gif")
    no-repeat left top;
  margin:0;
  padding:0 0 0 9px;
  border-bottom:1px solid #765;
  }
#header #current {
  background-image:url("left_on.gif");
  border-width:0;
  }

When we leave out a current tab, the effects of our style changes can be seen in Example 7.

Single-image Rollovers#section2

For the sake of simplicity, we intentionally left out the subject of rollovers in Part I. Now that we have the basic technique under control, we can start combining it with others to expand the utility and behavior.

Until recently, implementing any kind of rollover effect — whether with JavaScript or with CSS — meant creating two sets of images: one for the normal state, another for the hover state. To avoid a delay caused by separately downloading the hover-state image, numerous methods exist for “preloading” the required images into the browser cache. Petr Stanicek (aka “Pixy”) shows us in “Fast Rollovers, No Preload Needed” how to combine both states (normal and hover) into a single image, eliminating the need for preloading.

For our example, we stack our two left images on top of each other to combine the normal and hover states into one new image. We do the same for the right image. What were once 150-pixel tall images are now 300 pixels tall. We end up with left_both.gif and right_both.gif. With these new images, we can take advantage of the CSS background-position property to shift into view the appropriate portion of the combined-state background image when the user hovers over a tab:

[When the combined-state background image is positioned at the top of the doorway, the normal state is visible. When we shift the background image up by a certain amount, the hover state is visible.]

We switch to these new images for the list item and anchor, keeping the same position:

#header li {
  float:left;
  background:url("left_both.gif")
    no-repeat left top;
  margin:0;
  padding:0 0 0 9px;
  border-bottom:1px solid #765;
  }
#header a {
  float:left;
  display:block;
  background:url("right_both.gif")
    no-repeat right top;
  padding:5px 15px 4px 6px;
  text-decoration:none;
  font-weight:bold;
  color:#765;
  }

When dealing with the background-position property, we must specify two values,  horizontal and vertical, and they must be specified in that order. We can’t combine keywords (left, right, top, etc.) like we’ve been using with length or percentage values. So when specifying positions for the hover state, we avoid using keywords altogether. We use 0% for the left image to position its left edge against the left side of the doorway, and 100% for the right image to do the opposite.

Since we know exactly how far down in the new image each different state begins, we can vertically position the background images by a precise pixel amount. The top 150 pixels of these images holds the normal state, the bottom 150 pixels holds the hover state. So for both left and right images, we simply push the background images up by using a negative value of 150px. We also double up on the selectors for the first rule so we only need to specify the text color once:

#header li:hover, #header li:hover a {
  background-position:0% -150px;
  color:#333;
  }
#header li:hover a {
  background-position:100% -150px;
  }

We can use the same combined-state images for the current tab. Instead of specifying a new image as we were previously doing, we use the same shifted background positions from the hover states:

#header #current {
  background-position:0% -150px;
  border-width:0;
  }
#header #current a {
  background-position:100% -150px;
  padding-bottom:5px;
  color:#333;
  }

Implementing rollovers is as simple as that. See them in action in Example 8. We’ve dropped the total number of images we’re using from five (2 left, 2 right, and 1 background behind the tabs) down to three (1 left, 1 right, 1 background), and eliminated the need to do any image preloading.

If you’ve been checking our work so far in Internet Explorer (Win or Mac), no doubt you’ve noticed that the rollover effects, as implemented above, don’t work. IE only applies the :hover pseudo class to anchor elements, nothing else. In order to change both images of the Sliding Doors technique, we would need to insert an additional element (such as a span) inside the anchor, and shift all our style rules one element inward (list item rules shift to the anchor, anchor rules shift to the span).

We won’t review in detail the adjustments required to get both images changing for a rollover effect in IE. But to prove it is possible, we can see these changes demonstrated in Example 8a. As you can see, shifting the roles of each element also eliminates the small amount of dead space we mentioned in Part I, because the anchor now contains the entire tab.

Rollovers are often (more-or-less) a decorative effect. Some of you may decide the extra markup needed isn’t worth the advantage of getting rollovers to work in Internet Explorer. Others may decide the extra spans are a small sacrifice to have rollovers working in all popular browsers and to eliminate the dead space in previous examples. Whether or not to insert the extra markup is up to you.

Clickable Region Fix#section3

As in the case of our tab examples from Part I, navigation links can be turned into block-level elements and given extra padding to increase the clickable region of the link. The visual region is most often filled with a background color (or background image in our case) which implies that the user can click anywhere within this region, not just on the contents of the link. In most browsers, when an anchor element is changed to a block-level element (via CSS) and additional padding is applied to this anchor, its visual and clickable regions expand together to cover the contents and the padding of the link. Unfortunately, IE/Win will only expand the visual region, confining the clickable region to the anchor’s contents, not inclusive of its padding:

[The clickable region in most browsers expands to the entire visible area of the tab, but Internet Explorer for Windows will only make the text clickable.]

In Part I (and just after Example 8a above), we briefly mentioned a small amount of dead space on the left side of the tab caused by the transition to transparent-corner images. We also noted the requirement to avoid this dead space. However, Part I avoids covering the limited “clickable region” issue in IE/Win. This browser (version 6.0 and lower) suffers from several bugs in its implementation of CSS. One of the bugs produces unintended — and sometimes unrecognized — problems in the usability and accessibility of CSS-styled navigation.

Specifying either width or height for the anchor will magically force IE to expand the clickable region as well. But doing so would inhibit the flexible size of our doorway in other browsers. For our tab example, you might think we could use the “ems” unit to specify a width or height. This would size our tabs based on the already-inherited font size of the text inside. But specifying a height for the anchor makes IE/Win go bonkers. And unless we’re using a monospaced font for our tab text, specifying a width in ems will make the tab width inconsistent with the text inside as it gets resized. (Not to mention the pain of determining an appropriate width for each piece of text, then needing to re-specify the width every time the tab text gets changed.)

Fortunately for us, we can exploit a different flaw in IE/Win’s implementation of CSS, forcing the expansion of the clickable region in this browser, without needing to guess at an arbitrary width. All we need to do is specify a small width for the anchor. Most browsers will pay attention to — and honor — the width property for a block-level element, even if the contents inside the element don’t fit within that width. The element will shrink to the specified width, even if it makes the text inside poke beyond the element’s boundaries. But IE/Win will only shrink the element to the width of the longest non-wrapping line of text.

So even if we specify a tiny width for the anchor (like .1em), IE/Win will still allow the anchor to be as wide as the text inside. At the same time, IE will also expand the clickable region to fill the entire tab:

#header a {
  float:left;
  display:block;
  width:.1em;
  background:url("right.gif")
    no-repeat right top;
  padding:5px 15px 4px 6px;
  text-decoration:none;
  font-weight:bold;
  color:#765;
}

This makes no sense whatsoever, as the two concepts work in direct opposition to each other. But it works, and fixes the clickable region for IE/Win. We need to keep in mind that other browsers honor this width specification, and will actually attempt to shrink the width of each tab down to .1em + padding. Happily, IE/Win (6.0 and lower) also doesn’t understand the CSS child selector — so we can use one to reset the width of the anchor back to “auto” for all other browsers, allowing the tabs to expand and contract as normal:

#header > ul a {width:auto;}

Example 9 will fix the clickable region problem in IE/Win, and its sad little IE-centric hacks should be invisible to all other browsers.

Targeting Tabs#section4

All examples in Part I used an ID applied to a single list item to alter the appearance of the “current” tab. The result of moving the ID from one list item to another is an easy concept to understand for someone new to CSS. But an alternate means of targeting the current tab may be more efficient in many cases, even though it adds a small amount of markup.

Instead of using a single id=“current” to identify the current tab in the markup, we can apply unique IDs to each list item, like so:

<div id="header">
  <ul>
    <li id="nav-home"><a href="#">Home</a>
  </li>
    <li id="nav-news"><a href="#">News</a>
  </li>
    <li id="nav-products"><a href="#">Products</a>
  </li>
    <li id="nav-about"><a href="#">About</a>
  </li>
    <li id="nav-contact"><a href="#">Contact</a>
  </li>
  </ul>
</div>

We also apply an ID to a larger containing element (like the body). The ID value corresponds with a section into which this page fits. This body ID can also be used to add unique section-specific styles to other portions of the page. With IDs in both places, we can alter the appearance of a certain tab if it meets the conditions of descendant selectors. Rather than use #current as part of our selector, we’ll use combinations of body and list item IDs to set the conditions for when a tab is considered “current”:

<strong>#home #nav-home, #news #nav-news,
#products #nav-products, 
#about #nav-about,
#contact #nav-contact {
  background-position:0% -150px;
  border-width:0;
  }
#home #nav-home a, 
#news #nav-news a,
#products #nav-products a, 
#about #nav-about a,
#contact #nav-contact a {
  background-position:100% -150px;
  color:#333;
  padding-bottom:5px;
  }

Example 10 displays the effects of applying id=“news” to the body, and Example 10a shows what happens when the body uses id=“products”. {A List Apart’s navigation uses body id the same way. – Ed.}

Additional Notes#section5

Box-tops: You may have expandable modules on your pages which draw a box around a header and its supporting content. Assuming that you’re using a wrapper (like a div) which contains the module’s header and content, you already have the two elements for each background image (the div and header). In this case, you’ll most likely want to place the narrow image on the right, as shown in Example 2. This will give you complete control over the left starting point of the heading text. Fade the bottom of each image into the background color of the containing box so they appear to blend together as one unit.

Turning Sideways: If you can roughly predict the height of an interface element, (or if you create an image large enough to accommodate vertical expansion) you can turn the “doorway” on its side, using one image for the top and one for the bottom (instead of left and right). Remember to take into account extreme text wrapping which might occur with narrow browser widths or enlarged text sizes.

IE Flicker: If you’re seeing a flicker of the images when hovering over the tabs in IE/Win, check the cache settings for temporary files (Tools > Internet Options > General tab > Settings button). You may have changed the setting from the default to make sure you’re seeing the newest version on every page refresh. IE/Win has trouble holding a background image steady on anchors if you’ve specified “Every visit to the page” for temporary files. The default setting is “Automatically”, which allows the browser to instantly retrieve the image from cache, preventing any flicker. Most users never change this setting; most likely, they don’t even know it exists.

Multi-word Tabs: As may often be the case, if you need to use text for a tab that consists of more than a single word, you’ll most likely want to add a white-space:nowrap; declaration to the anchor rule, preventing the tab text from wrapping in certain browsers.

There might be other issues, alterations, and variations on this technique which already exist, or crop up over time. But we’ll stop here for now. Hopefully we’ve filled in gaps and resolved a few uncertainties surrounding the usefulness and extensibility of Sliding Doors. Onward and upward.

About the Author

Douglas Bowman

Founder and principal of Stopdesign, Douglas Bowman specializes in simple, clean, forward-thinking design. He constantly challenges and pushes the limits of what’s possible using web standards. Douglas was the grand architect behind the well-known redesign of Wired.

101 Reader Comments

  1. A fantastic article, and it caters for all levels of hacks.

    Some people don’t want to add muck mark-up, others don’t mind a little.

    I bow down to this ground-breaking CSS expert!!

  2. …to what CSS has to offer, Doug! Not to mention great work on the graphics for the article, Outstanding stuff.

    It would be neat to work in something like Kalsey’s Tabs, with the secondary tabs built in as nested lists…Hmm…

  3. This has been a great read, definitely a useful tutorial on advanced tab navigation. One thing I’m wondering about is the use of classes/ids to identify the current navigation section. Instead of

  4. Current Tab
  5. it seems like it would be helpful to provide some highlighting for the stylistically challenged:

  6. Current Tab
  7. Thoughts? Comments?

  8. Michael: It would certainly be possible to insert in addition to (or in place of) the anchor. This is something I do for the current navigation on Stopdesign. It seems appropriate to emphasize the current tab text with , especially for cases where users see an unstyled (or stripped down) version in a text-only browser, or a screen reader which might pronounce emhphasized text differently. It would just mean adding a few additional selectors to the style sheet to “conditionalize” a little differently.

    Because some of the styling is applied to the list item, I think you’d still need to have some additional way of identifying the “current” list item, whether that be through the original id=”current” method from Part I, or the alternative method from Part II. If all the styles are moved inward one element (as in Example 8a) you could get away without using any IDs.

  9. The tab still disappears on mouseover with IE 6, in-fact it’s a bit worse now. Sometimes the original tab image doesn’t reappear and your left with nothing but text.

    My settings are on “auto” like the article says.

  10. In our tests here in IE6/Win it works exactly as described in the article.

    Not that that helps you or eases your pain. Perhaps another preference setting is to blame.

    Browsers! Can’t live with ’em, can’t live without ’em.

  11. All of your examples seem to be flickerless on IE6/Win98SE, but on my (home) IE6/XP computer, they flicker with any cache setting. I’m using IE 6 XP (“Gold”) with SP1. The exact version is 6.0.2800.1106.xpsp2.030422-1633. It has all the updates I’ve found applied to it. Is this a flaw in your method, or an obscure bug that has only ever happened to me?

  12. This is some really beautiful stuff. I was really impressed with the first, and honestly didn’t see how it could get much better, but you definitely proved me wrong.

  13. Martijn, I just had a look at your example with Opera 7.11/linux and all tabs are sitting on the left on top of each other without any background grafics.

    Andreas

  14. Both articles are very inspiring and very succinctly written. I enjoyed reading them and took home a lot of new insights. Thanks, Doug.

    Andreas

  15. Andreas: I have checked on Opera 6.03 on my Mac and a fresh copy of Opera 7 on Win98, but they both make a mess of both the CSS in the article and my own example.

    Tweaking a local copy of a HTML file and a stylesheet and reloading in Opera 7 did not show any difference, even not when emptying the cache and restarting Opera.

    Even more interesting, this website (A List Apart) uses the same technique for its top menu, but not the IE/Mac hack and it still works.

    Can anyone shed a light on this? I like my stylesheets with as less hacks as possible and it seems there are more roads leading to Rome when using list-items for a menu and marking them up with CSS to align them horizontally.

  16. I am using Mozilla, but tested it on IE 6 under Win2k and no flickering occurs when the cache is set to auto. However I prefer using every time check, so it’s less useful for this option (doesn’t look good).

    Regardless of this IE bug, this article is way to go! Thanks for sharing your tips.

  17. Congratulations Doug for refining the sliding doors even further; however I’d like to print those 2 articles for back reference w/o the menubar and sidebar widgets.
    A shame that ALA doesn’t have a print style sheet ready yet.

  18. Very nice! I’ve been experimenting with tabs too and this will certainly come in handy. One caveat I’ve noticed though, is when you have a large tab row (try making the fonts extremely large in one of the examples). Depending on the browser, the tabs are then stacked in different rows or wider then the content.
    The only way around that seems to be limiting the width of the tab row to the width of the content below it, which may not always be possible.

  19. Nice article, congratulation.
    While trying out with IE6/XP (Version:6.0.2800.1106.xpsp2.030422-1633) the example 8a functioned perfectly. However, with the examples 9 to 10a was not to see any hover effect, up to the changing of the font color.

  20. Wow, I guess we’ve found a really wierd bug in IE6/XP. I tried it with another browser of the exact same version (6.0.2800.1106.xpsp2.030422-1633), and the flicker did not occur. The browser’s cache setting is set to “Automatically”. Maybe it has something to do with a plugin. I’ll test it later when I get home. Here’s a list of my plugins:
    -Google Searchbar (the newest one)
    -Download Accelerator Plus (toolbar not showing)
    -Yahoo! Companion (newest version)
    -Some XML/XSLT extension I downloaded of the net

    For other people with the flicker, what plugins do you have?

  21. Great follow-up article, can’t wait until I see someone like amazon use these techniques.
    Anyway, I was working on a site (http://www.axonodesign.com/) using pixy’s rollover effect and had the flicker problem still occur after changing my settings in IE6. The problem however was on the Apache server I was using still causing it to flicker. What I did was for Apache servers 1.3.6 and later. I use these lines in the into the httpd.conf or .htaccess file. to disable Vary headers
    for the IE browser

    BrowserMatch “MSIE” brokenvary=1
    BrowserMatch “Mozilla/4.[0-9]{2}” brokenvary=1
    BrowserMatch “Opera” !brokenvary
    SetEnvIf brokenvary 1 force-no-vary

    It worked after that with no flicker.

  22. Blakems said: “can’t wait until I see someone like amazon use these techniques”

    I think someone else will renew it’s tab method first
    😉

    btw, outstanding article: thanks to the ALA staff!

  23. Awesome article, Doug.

    I just wanted to note a variation on the current state that may be useful to some.

    Here, since we regularly use includes for our navs (for consistency) it isn’t possible to just class an

  24. as current… each page would need it’s own nav.

    To get around this, we class the of each page instead, then reference the different styles thusly…

    body.home ul.nav{
    }

    or

    body.aboutus ul.nav{
    }

    Works like a charm, and only requires one markup of the list.

  25. If there are any spaces around the child selector, IE5.0 (Windows) will apply the style rule, so:

    li > a{color:green;} /* green in IE5.0 */
    li>a{color:green;} /* default in IE5.0 */

    For the rest, great article!

  26. I’m using IE 6 on IE with all patches too. Matching the version numbers with those others with problems. Plugin wise i don’t have the same, mainly IE spell and flashget.

    Tested on machine at work. WinME with IE 6 works fine, tested on our XP machine and it does not!

  27. Sorry to intrude yet again on the same subject, but my slow brain is starting to understand.

    If you omit the IE5/Mac hack in the code and you insert both the display:block and float:left into the css declaration for the a-tag and the li-tag, does that only cause a problem in Opera 7, or do other browsers encounter serious problems as well?

    I have tried to understand what is written about the float property on the W3C website and googled around a bit, but I cannot detect if a float in a float in a float — starting to sound like nested tables — is not permitted theoretically.

    The upside of all this: a lot of people are working with the concepts of this article right now and for that I have to say that this seems to be the most inspiring ALA article since the article about ALA version 2.

  28. … on my PC running Windows ME.

    No blinking noticed.

    Maybe XP has something to do with that.

    I love this article on Tabs. I’ll draw a different model of Tab (a slanted one) and then will try it with a Web Page I’m working on.

    I’ve been trying to find a nice CSS Tab to use for quite a while, and if it’s working as well as it looks, and with most Browsers, I will adopt it…

    Thanks for coming up with it.

    Oh, and what I really need is a system with Subnav Tabs, like this one here at http://www.homelesspixel.de/tabs/tabs.html, which was my favorite until now.

    Gilles C

  29. Thanks for the great article! We are now using the tabs on our site, which launches tomorrow.

    A quick thought from a usability perspective – the current tab shouldn’t really be a link since the link will just take the user back to the current page. We solved the problem by still using an anchor, but not specifying an href for it:

  30. Current Tab
  31. Works everywhere and still validates.

    Jay

  32. Great article. I was thinking that it would be nice if, say, list-o-matic was able to take the concepts outlined here and distill them into a 15-steps (or however many)tutorial, without all the extra stuff that Dave throws in that might scare some people off.

    Now that would be truly useful!

  33. I’m wondering what a screen reader would do with the

    tag. Do you know why the

      tag has been used for menus instead of the

      tag? Wonderful article, thank you this and the additional articles you have on your web site.
  34. Works fine with IE 6 and XP with all the patches from MS. No flicker and really beautiful. I don’t mind the extra hack for IE, it’s part of programming. Everything can’t be perfect as much as we would want it to be.

  35. I’m having flicker problems here too. I haven’t been to one site that’s been posted thus far in the discussion of this article that uses this technique (or any variation of it) that displays the rollovers without flickering.
    Nevertheless, great article. Let’s see if we can figure out this IE6/WinXP bug though.

  36. I thought that CSS was originally created in order to make our lives easier when it comes to designing effective web sites. However, I get the impression that things are just getting more and more complicated. Out of hand, really. These kind of gymnastics need to be built into the technology as integral elements, not as bits and pieces which in the end could capsize the ship.

  37. When I tried to apply the fix given to my site’s menubar, Moz Firebird .7.0 on Win98 didn’t pickup the > selector reapplied width. The example works just fine so it’s something about how I adapted it to fit my code. IUf anyone has a few minutes… Thank you:

    ul#menu li
    {
    float:left;
    font-size: 140%;
    margin:0;
    padding:0;
    }
    ul#menu a
    {
    width:.1em;
    float:left;
    display:block;
    padding:0;
    margin: 0 .125em;
    font-weight: bold;
    text-decoration: none;
    }
    ul#menu>a {width:auto;}
    /* Commented Backslash Hack
    hides rule from IE5-Mac */
    ul#menu a {float:none;}
    /* End IE5-Mac hack */
    ul#menu a span
    {
    display:block;
    margin:0;
    padding:5px 15px 4px;
    }

  38. Super!

    Here is to give you an idea of how I want to use it.

    http://www.gtechblues.com/gtblues2.html

    It’s far from being finished, I just patched your tabs with what I was using so far to see if I could use your idea with a submenu. I took out the topnav tabs and replaced them with yours and bingo, it’s still working the way I want.

    At least now I know that I can put some more time on it to get a page with a better look… and a cleaner source without extra stuff.

    Thanks.

  39. It’s an interesting technique and a good tutorial. The problem is that if the window isn’t wide enough for the tabs, they wrap downwards. In my opinion, it looks unprofessional. It’s can be more of an issue when it occurs in the user interface of a web application. If you have a solution to that problem that doesn’t involve hard-coded widths, I’d love to see it.

  40. I’ve been trying to implement this code to work from an external stylesheet on IE5.2 Mac OSX. It works in every single browser I’ve got on both PC and Mac (Opera, Mozilla, Safari etc) except ie5.2 – it does work when I place the stylesheet in the XHTML document, but as soon as I try to refer to it externally (either as a LINKed file or as an @import) the formatting breaks. Some of it gets through (colours, no bullets on the list) but other than that it’s still formatted like a list, and the background images are ranged over to the other side of the screen and displayed in all their 400px wide glory.

    Anyone else experienced this truly frustrating phenomena? I don’t want to have loads of css info in the headers of all my documents, and definitely don’t want to do any browser checking.

  41. I’m getting the flicker effect as well, regardless of browser cache settings.

    Based on the number of people reporting this issue on configurations that are very common (IE 6, win2k, winxp), i’d be concerned about using this technique in production just yet.

  42. After a week and a half of testing this on every machine I could find — a mix of 98/2k/XP machines, some at various cafes, friends parents’ houses, public terminals, and even some slow-rendering copies of Virtual PC (some on broadband, at least 4 on dial-up) — I couldn’t replicate any problems of background-image flickering. And I really tried. I looked everywhere I could. As long as IE/Win was left at the default cache setting (“Automatically”), with a reasonable amount of disk space reserved for temp files, the images held completely steady as many times as I moused over them.

    All of the machines tested (15-20) were standard-issue real-world machines, usually with default settings left in place. Outside of un unknown browser bug we haven’t yet uncovered, I supsect some of the development environments used by more experienced ALA readers may have just enough customized to prevent standard image caching.

    Either that, or could somehow be a web server setting. I’ve seen some blogs on Blogger’s blogspot domain where background images applied to anchors flicker every single time. When files were moved to another server, they were fine (with same browser settings).

    If anyone can figure out what the oddity is that’s causing a few people to see image flickering (besides the wrong browser setting), we’d appreciate it. Thanks for the feedback.

  43. I’ve been wondering this for a while now… what’s the deal with the three digit colors in the style sheets? For instance, in this article, the author has this in his style sheet (I took the unnecessary attributes out):

    #header #current a{
    color: #333;
    }

    Is this correct? Why not #333333?

  44. Well, for some proof of the bug’s existance, I’ve captured screenshots of the flicker (very hard to do, only does it for a millisecond on broadband) and the hover state of the tabs. I believe it’s not been metioned, but the tabs don’t change backgrounds (move the background image), but just change text color. Here’s some images. Shure hope this can be fixed, because it sure looks great in Mozilla!

    http://www.treespasm.com/rajeev/tabs/flicker.png
    http://www.treespasm.com/rajeev/tabs/hover.png

  45. Note to everyone, in case it wasn’t clear: Example 8a is the only version which includes extra elements to get the hover change working in IE.

    After Example 8a, I dropped the extra span intentionally and reverted to the cleaner version — so there isn’t any hover effect for Ex. 9 and 10 in IE, other than the text color. If you want the hover working in IE, see Example 8a, and its brief mention in the article text.

  46. The whole concept is looking good,
    but why use a single image, when it might cause problems?
    As to me 2 images(normal/hover) are easier
    to work with, especially when you need to develop variations.Of course you dont need a preloader, just put the over image into
    a hidden layer on top of the page.

    askinya xoxlitude

  47. I’ve used some of this CSS code in another project (not tabs), and stumbled on a problem with IE/Win region fix.

    If the name has more than one word (try Our products instead of Products), that tab item will break into two lines (to be precise number-of-words lines).

    Solution is to code it like this:

    *html #header a {
    width: .1em;
    white-space: nowrap;
    }

    This works in IE 5.5 and 6, but not in IE 5 which doesn’t support white-space property. So, you can either neglect that, or you can make width: 8em or some other possible value.

    Or you can ignore it completly if you have high-enough background images.

    Thanks to Tantek, IE 5.x hacks can be placed to separate file to deminish the updating problem.

  48. Hello Doug, Thank you for this wonderful tutorial, I’ve learned so much. I noticed the difference in the examples given for 8a and 9 and 10.

    so I’m am trying to incorporate both examples of the WinIE hover fix to the targetted tab via the Id.

    So far..I’m close..but it’s tricky and I’m still unsuccessful. It seems that the targeted tab code gets wiggy with the rollover code.

    I have the rollover code working, but the target tab ends up being the images reversed in color and orientation. I’m thinking the span tag has something to do with it.

    I wondered if you have solved this and can offer a hint. I’ve enjoyed playing with this code and love the brevity of it.

    Mahalo – Haunani

  49. hi, I figured it out. I added span code to get the functionality working the way I wanted
    code:

    #home #nav-home,
    #news #nav-news,
    #products #nav-products,
    #about #nav-about,
    #contact #nav-contact {
    background-position:100% -150px;
    border-width:0;
    }
    #home #nav-home a,
    #news #nav-news a,
    #products #nav-products a,
    #about #nav-about a,
    #contact #nav-contact a {
    background-position:0% -150px;
    color:#333;
    }
    #home #nav-home a span,
    #news #nav-news a span,
    #products #nav-products a span,
    #about #nav-about a span,
    #contact #nav-contact a span{
    background-position:100% -150px;
    color:#333;
    }

  50. Haunani, is this a fix for the IE6/XP problem or your own personal brew? If it is the fix, please post the complete source! (example number edited, CSS changed, markup changed)

  51. In ex: 8a, after having shifted styles around, Doug is instructing the header list items to display inline and the header anchors to float left. If the list items are already instructed to display inline, why is it necessary to float the anchors contained in the list items to the left? If you don’t do this, the layout falls apart, but I can’t figure out why. I’m sure there is a simple explanation, but somehow I’m not grasping it.

  52. I’ve controlled the multi-word tabs from wrapping with white-space:nowrap; but the menu I have is wider than the page in low res (800×600) and the list items wrap. white-space:nowrap; doesn’t seem to work if applied to #header or #header ul. Any ideas?

  53. I used the sliding door concept at eldoradosurgicenter.com but now the customer wants the tabs and subnavbar to stay at the top when scrolling. Obviously, this can easily be done using frames. However, how does one call up the “Current” set of tab images when using frames? i.e., when a user clicks a tab, the tab that was clicked is highlighted. How do you achieve that with the sliding door concept in frames?

  54. When I implemented the sliding door concept at eldoradosurgicenter.com, the navbar div (the one with the tabs) was superimposed on the following div which is the subnavbar when using Mozilla Firebird, Konqueror, and Galeon. This does’t happen with IE 6.

    In order to get around this (where one div overlaps the following div), I had to place the tabs bar and the subnavbar into a table. Obviously, I don’t like that. How can I get the browsers in Linux to display one div right after the a previous one without overlapping? Btw, this only seems to occur when there are floats involved.

  55. Truly informative article!! But with all the issues raised (some solved, some not) couldn’t someone compile the source code + fixes somewhere so it’s easy to copy n’paste?? Just for the sake of not having to go through the 2 articles + 7 pages of comments… :/

    Hope this XP bug gets sorted. That is the only thing that makes me reluctant to use it for a client’s site yet.

    Pukka!/Awesome! (delete accordingly)

  56. Wow, this is really weird. When I started up my browser, the flicker stoped happening. Maybe this is one of those “automatic IE updates” (I read they existed on quirksmode.com, but they haven’t been proved to exist). Anyone else experiencing this?

  57. Thanks Doug! It’s superb, especially with the niceties added in part II.

    What do you recommend as a technique for centering the set of tabs in the viewport? A quick stab at putting text-align:center on the ul didn’t do it.

  58. First of all, my compliments: both articles are clearly written, have great examples, demonstrate (highly!) impressive CSS acumen and the resulting tabs _look_ great.

    That said (and I know I’m going to get flamed for this, but so be it…), I have to take strong exception to the section of (Part II) entitled “No Current Tab”. You just CAN’T have a set of tabs without one of them being selected. Period. Full stop. No exceptions–don’t do it! (And yes, I _have_ seen countless examples (for example, the old Yahoo) where people _have_ attempted to do this anyway.)

    To clarify, what I mean by “CAN’T” is not that it is _technically_ impossible (of course it is possible, as Example 7 in the article demonstrates), it is just really, really unwise. So, I’m saying “can’t” in the sense that you “can’t” let your two year old play with a lighter or matches.

    Look, these CSS-generated ‘tabs’ (and the similar GUI widgets that they are modeled on) are actually just visual metaphores for a real (physical) set of tabs . . . like you’d see on manila folders and on file cabinet hanging folders. Now with the physical folders, one (and only one) folder _has_ to be in front. You can’t have two (or more) of them simultaneously be front-most.

    Right about now some may be thinking: hey, we’re in the virtual (not physical) world here; why don’t we break free of the restraints? Well, not only does having “no current tab” break the metaphore, it causes serious usability problems.

    If you don’t have one of the tabs selected (current), then the user _does not know where they are_ in reference to the (implied or apparent) navigation that the set of tabs supports. And if they are unsure as to where they are now, they will also have a (much) more difficult time deciding where to go next. Now if your navigation is simple and the navigation paths are clearly labeled (again, think of Yahoo), then the latter difficulty is lessened (but is still there); for unfamiliar site/applications; poorly labeled paths; or branching navigation flows the difficulty will be worse.

    For completness’ sake, I should also mention that using tab sets for open-ended navigation (like Yahoo does) or for “a registration process” (as the article mentions) or any other process for that matter, is just a bad idea in the first place. If their usage is confined to just using them as they were originally intended (i.e. to space-multiplex a lot of GUI elements in an overall fixed-size area–for example: for property sheets) then these problems can be avoided.

    Thanks for listening;
    let the flames begin… 😉

  59. I ran through this excellent tutorial and am excited to try out the techniques discussed.
    I thought I’d mention that IE will never cease to amaze. Throughout the article, I noticed the clickable region problems (using IE 5.5). Throughout Part 1 and including Example 7 in Part 2, my clickable region was faulty. Then in Example 8 my clickable region was fixed to include the entire tab. However in the final version (Example 9), my clickable region returned to the smaller region: the entire tab, but missing the left image area of the tab.

    Figured I’d point this out since lots of people are still using IE 5.x.

    Thanks for the great two-part article!

  60. This design seems to assume that the tab content will come after all the menu items. Changing tabs involves a server round trip to update the tab content.

    Is it possible to combine some of the techniques used in the suckerfish article with this article, plus a little javascript magic, to avoid this round-trip?

    My markup might look like

    • Tab 1 title
      …. content of tab 1
    • Tab 2 title
      …. content of tab 2

    I can see how I can use display:none to hide the content of the inactive tabs, but how do I get the div content under the active tab to appear below ALL the tabs? I’d like the content to somehow “float” beneath all the tabs.

    Thanks

  61. What about using the ‘behavior’ property in IE and creating an HTC file to access the background position of the parentNode instead of adding extra span tags to accomplish the same thing? And then in doing so, you could remove the box model hack and reset the height and width in the HTC. This certainly keeps your HTML simple, although, at the cost of a more complicated implementation of having to create an HTC file.

  62. Just use a single image of both complete tabs.The way the background images are positioned and overlapped, there’s no need to use seperate images for the left and right. This saves an image request and any worry that the two slices optimized my end up with slightly unmatched palettes.

  63. Yes! I’ve figured out the source of the IE6/XP bug! When I was scouring the settings of the XP machine that worked, I noticed that the cache size was set to a small amount (20MB). My cache on my home machine (which displayed the bug) had a cache size of 895MB (by default). When I changed it to 20MB, everything started working. It seems that with a larger cache size the browser does not check for newer versions of files at the right time. Well, at least we know it isn’t a code error!

  64. Hey guys,,

    I also moved to tableless layouts as most of you did. but there’s still one situation where I use tables. when I need to keep certain graphic or text element at the bottom of the page (something like here http://www.mldgroup.com). How should I resolve this with div’s?

    thanks,,

  65. I also had the flicker problem with IE6/W2K. Reducing the cache size to 20MB eliminated the flickering of the tabs.

    I’m not sure this resolves anything, since the flicker problem remains unpredictable.

    Does anyone know what is the default cache size setting for IE6? Thanks.

  66. This works flawlessly! However we have a need to place an image of a line (not a line that can be mocked up by a border) at the bottom of the tabs and hence in the BG

    Challenging, even when you adjust the padding to the depth of the imaged line, because the sliding left door wants very badly to be in front (the whole point, right!) and gets in front of the bg image no matter how you pad it.

    So … we need to either bring the BG forward or slide the left door behind the bg but still in front of the right door.

    Ideas? z-axis?

    R.

  67. Okay. I’m not intelligent enough to add Step 8a’s IE fix to Step 10a. Everytime I try weird stuff happens. I spent an hour on it last night and just couldn’t work it out. Sad, I know. Could someone please help me or post the answer outright?

  68. I got rid of the flicker by clearing my cache. Works fine now. The ability of the tabs to resize is awesome.

    But, given this flicker problem (caused by the browser, not the code), would any professional web designers implement this technique on a highly visible site? I’m especially interested if Doug would feel secure using it on a site such as http://www.adaptivepath.com.

    I don’t think I could =/

  69. If anyone has the full code (up to step 10a) with the IE rollover fix included, I would be grateful if you could post it here.

  70. I am going to take a new approach for my Japanese web site.
    The sliding door is a great article and definitely I want to use on my pages.

    I tested all the examples (example 1-10) and I found a problem with Japanese character environment. If I reduce browser’s width, it start character wrap within a tab, further reducing window width a tab itself wraps.
    This does not occur in alphabet characters.
    Is there any fix for this?

  71. I forgot to tell one more point.
    Tab words of example 10 is complete vertical writing regardless width of windows.

    I can send html pages which show the problems if anyone challenges fixing this issue.

  72. Did anyone correct problem with MSN for MAC OS X ? In this browser tabs looks like in Safari (100% width) without hack…

  73. Did anyone correct problem with MSN for MAC OS X ? In this browser tabs looks like in Safari (100% width) without hack…

  74. I think that many people had problems incorporating the IE rollover fix into example 10. This is what I came up with:

    body {
    background: #fff;
    margin: 0;
    padding: 0;
    color: #000;
    font: x-small/1.5em Georgia,Serif;
    voice-family: “”}””; voice-family:inherit;
    font-size: small;
    }

    html>body { font-size: small; }

    #header {
    float: left;
    width: 100%;
    background: #dae0d2 url(bg.gif) repeat-x bottom;
    font-size: 93%;
    line-height: normal;
    }
    #header ul {
    margin: 0;
    padding: 10px 10px 0;
    list-style: none;
    }

    #header li {
    margin: 0;
    padding: 0;
    display: inline;
    }

    #header a {
    float: left;
    background: url(left_both.gif) no-repeat left top;
    width: .1em;
    margin: 0;
    padding: 0 0 0 9px;
    border-bottom: 1px solid #765;
    font-weight: bold;
    color: #765;
    text-decoration: none;
    }

    #header a span {
    float: left;
    display: block;
    background: url(right_both.gif) no-repeat right top;
    margin: 0;
    padding: 5px 15px 4px 6px;
    }

    #header>ul a { width: auto; }

    /* Commented Backslash Hack hides rule from IE5-Mac */
    #header a span { float: none; }
    /* End IE5-Mac hack */

    #header a:hover span {
    color: #333;
    }

    #home #nav-home a, #news #nav-news a,
    #products #nav-products a, #about #nav-about a,
    #contact #nav-contact a {
    background-position: 0 -150px;
    border-width: 0;
    }

    #home #nav-home a span, #news #nav-news a span,
    #products #nav-products a span, #about #nav-about a span,
    #contact #nav-contact a span {
    background-position: 100% -150px;
    padding-bottom: 5px;
    color: #333;
    }

    #header a:hover {
    background-position: 0% -150px;
    color: #333;
    }
    #header a:hover span {
    background-position: 100% -150px;
    }

    It works fine for these browsers:
    – Internet Explorer 5.01 SP2
    – Internet Explorer 5.5 SP2
    – Internet Explorer 6.0 SP2
    – MSN Explorer 6.0
    – Mozilla 1.5
    – Mozilla Firebird 0.7
    – Netscape Navigator 7.1
    – Opera 7.11

    If you find any bugs, please post here.

  75. i’ve taken liberally from doug’s techniques to add drop downs to a very similar menu layout. i’ve got a working solution in the latest gecko browsers, ie 5+, opera 7.11 (windows). on the mac side it works in safari and gecko browsers, but goes absolutely wacko in ie 5.2. view it here – http://rzand.homedns.org:8080/main/home

    btw, this layout seems to be more browser friendly than the brainjar example, another demo i have borrowed heavily from. anyone seen this before and have any ideas?

    btw, i’m sniffing the browser on the server side with php and including local styles that override those in the stylesheet rather than using css hacks.

  76. Rz, do you think it will help win Netscape 4 users over to your viewpoint to lecture them about what browser they are using?

    Actually, your site seems to work fine in Netscape 4 with JavaScript off. I just don’t see your interface work.

    And that’s actually the great thing about the technique in this article. If you have a modern browser, you see the cool stuff. If you have Netscape 4, the site still works.

    (Well, except for any links to a mid-page id, but aside from that.)

    Can’t upgrade to Netscape 6 until I buy a new Mac (requires OS X, which doesn’t run on an 8600), iCab crashes too much on my unit, and I’d rather not use IE, even if it’s IE/Mac.

    Call me stubborn, but it’s my attention you’re trying to get, and I’m darned if I’m going to buy a new computer just to visit your site.

  77. First off – yes, this is a great technique, and a very easy-to understand tute.

    I’ve been using these tabs to allow navigation through a one-way process (specifically an online ordering process) – the user can see where they are in the process, and click back to see or change previous steps/tabs. However, the user shouldn’t be able to click forward more than one tab at a time (if you’re one step one, you can’t jump straight to step 4)

    So – how can we create a tab which is disabled, or greyed out? If we remove the anchor element, we no longer have a second ‘sliding door’ to apply the style to…

    anyone got any ideas? preferably without introducing extra spans…fanks!

  78. Actually, it isn’t a broken or unusable interface. There are other homologous tab examples: cookbooks, reference books, VW Owner’s Manuals. In these examples, often you’ll see tabs for the referential content; but they are all still have preceding material before the first tab: cover, title page, contents, introductions.

    No flame. Just rebuttal. 😉

  79. In your first article about sliding navs you mentioned the abilility to put a logo in the header# – how do you ad this?
    Thanks – great CSS!

  80. Okay, not so mind-boggling, but certainly opens the lid on what CSS can do. Who would have thought compliance could be so ‘cool’ 😉

  81. Hi, I would like to ask if there is any posiblity to center

  82. “tabs” to the header div. I don’t want to center the header div but only ul and li. The reason is because I will dynamicly change amount of tabs and I can’t center it to the page right now without changing header width. 🙁
    For beter understandig you can look at
    http://www.daend.cz/FTP/WEB-templates/01/
    Right now it looks like tabs are + – centered. But if I remove one from the list it is not centered in the header div with black border.
    Thanks for your help.
  83. Hello everyone and many thanks for the article !

    Is there a way to make the tabs to evenly distribute themselfs when resizing the window ?
    Either by reduce/enlarge the gaps or by changing the tabs’ width.

    Thanks a lot in advance,
    Chris

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

Nothing Fails Like Success

Our own @zeldman paints the complicated catch-22 that our free, democratized web has with our money-making capitalist roots. As creators, how do we untangle this web? #LetsFixThis