Posts Tagged 'CSS&'

Jul

9

Yet Another Image Replacement Method

Posted by admin under internet, technology - 1 Comment

Semantic CSS Image Replacement

Yes, “YAIRM” (”Yet Another Image Replacement Method”) is a crappy acronym. Anyhow….

There have been several image replacement suggestions made over the past 5 years. Semantically, some just don’t make sense. Of course, the accessibility of your image replacement method and the semantic “correctness” has to do with how you code your HTML.

Pros

  • This method works for both in-line and block style elements.
  • Accessible to screen readers and non-image/non-screen media.
  • Does not add extra elements only for styling (no extra span).
  • Works cross browser

Cons

  • Using images for text does not allow for text resizing (like all IR methods).
  • Does not handle “images off/CSS on” scenario; but neither do most layouts with background images, such as the sidebar on this blog.

When I need to replace a header or some other text with an image, I simply give the element my image replacement class (<h1 class="imgreplacement">), and declare the background image, height and width I want to use either by providing an ID and defining the background image in the #id selector, or by targeting the element through specific/unique cascade. I place all of my image replacement css in a media=”screen”. Even though the media attribute is not heeded by all browsers, it is heeded by devices that are not screens. If your user than prints your webpage, the text that was replaced by an image in the browser will print as it semantically should.
button.imgreplacement { display:-moz-inline-box; display:inline-block; background:transparent none 0 0 no-repeat; text-indent:-3000px; font:0/0 Arial; overflow:hidden; color:rgba(255,255,255,0); vertical-align:bottom; background-image:url(http://www.evotech.net/articles/images/redx.gif); width: 18px; height: 18px; border:none; cursor: pointer, hand; }
Continue Reading »

Nov

16

Powering Javascript UI with CSS

Posted by admin under resource, technology - No Comments

If you have been doing any Javscript coding during the current Javascript renaissance, you will have noticed that a lot of the user interface functionality you build is hiding and showing things.

After a while of this you might find yourself coding up toggle functions, which find elements and toggle their visibility. togglePair, toggleVisibilityById, there are lots of these types of functions in javascript apps today.

I’ve been trying out a different way of dealing with the need to change the UI based on user inputs or asynchronous data events: CSS.

With CSS, you can use the DOM as a data model and then use declarative rules to establish the display. It’s cleaner, because you limit your javascript code to changing the DOM’s data instead of it’s UI, and then you use the extensive abilities of CSS to handle the visual representation of that data.

Here’s an example. A common thing to do with javascript seems to be expanding out a form to fill out. Livejournal does this with their login form, or 37Signal’s tadalist uses this when you want to add an item to your todo list.

here’s the just javascript way to do this:

<div>
  <span onClick='document.getElementById("form1").style.display="block";'>click me to add a comment</span>
</div>
 ...
<form id='form1'>
<textarea>add your comment</textarea>
</form>

But here’s the CSS + Javascript way to do it.
CSS Rules

form#addComment {

display:none;

}

form#addComment.editing {
  display:block;
}

Javascript + HTML

<div>
  <span onClick='document.getElementById("addComment").setAttribute("class","editing");'>click me to show form</span>
</div>
 ...
<form id='addComment'>
<textarea>fill in some data here</textarea>
</form>

This can prove really advantageous when you are radically changing the visual presentation of the page. Instead of finding and changing the style of tons of elements by id, you can change 1 element’s class and then use the inheritance of CSS to style all the sub-elements.

Nov

16

Sliding Doors of CSS, Part II

Posted by admin under resource - No Comments

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.

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

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

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

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

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

#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

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.

Nov

16

Sliding Doors of CSS, Part I

Posted by admin under resource - No Comments

A rarely discussed advantage of CSS is the ability to layer background images, allowing them to slide over each other to create certain effects. CSS2’s current state requires a separate HTML element for each background image. In many cases, typical markup for common interface components has already provided several elements for our use.

One of those cases is tabbed navigation. It’s time to take back control over the tabs which are continually growing in popularity as a primary means of site navigation. Now that CSS is widely supported, we can crank up the quality and appearance of the tabs on our sites. You’re most likely aware that CSS can be used to tame a plain unordered list. Maybe you’ve even seen lists styled as tabs, looking something like this:

[Ordinary example of CSS-based tabs, using flat colors and squared-off corners.]

What if we could take the exact same markup from the tabs above, and turn them into something like this:

[Stylized tabs using rounded corners and subtle three-dimensional shading.]

With simple styling, we can.

Where’s the Innovation?

Many of the CSS-based tabs I’ve seen suffer from the same generic features: blocky rectangles of color, maybe an outline, a border disappears for the current tab, a color changes for the hover state. Is this all CSS can offer us? A bunch of boxes and flat colors?

Prior to a more widespread adoption of CSS, we started seeing a lot of innovation in navigation design. Creative shapes, masterful color blending, and mimicry of physical interfaces from the real world. But these designs often relied heavily on a complex construction of text-embedded images, or were wrapped with multiple nested tables. Editing text or changing tab order involved a cumbersome process. Text resizing was impossible, or caused significant problems with page layout.

Pure text navigation is much easier to maintain and loads more quickly than text-as-image navigation. Also, even though we can add alt attributes to each image, pure text is even more accessible since it can be resized by users with impaired vision. It’s no wonder that pure text-based navigation, styled with CSS, is leaping back into web design. But most CSS-based tab design so far is a step back in appearance from what we used to do — certainly nothing to be included in a design portfolio. A newly adopted technology (like CSS) should allow us to create something better, without losing the design quality of previous table hacks and all-image-based tabs.

The Sliding Doors Technique

Beautifully crafted, truly flexible interface components which expand and contract with the size of the text can be created if we use two separate background images. One for the left, one for the right. Think of these two images as Sliding Doors that complete one doorway. The doors slide together and overlap more to fill a narrow space, or slide apart and overlap less to fill a wider space, as the diagram below shows:

[Diagram shows two sets of doors. The first set is pushed together to take up less space. The second set is spaced apart to occupy a wider space.]

With this model, one image covers up a portion of the other. Assuming we have something unique on the outside of each image, like the rounded-corner of a tab, we don’t want the image in front to completely obscure the image behind it. To prevent this from happening, we make the image in front (left-side for this example) as narrow as possible. But we keep it just wide enough to reveal that side’s uniqueness. If the outside corners are rounded, we should make the front image only as wide as the curved portion of the image:

[Diagram shows an isolated narrow left-side image with rounded top-left corner, then repeats that same image placed in front of a right-side image with a rounded right-side corner.]

If the object grows any larger than the width shown above, due to differing text or type size changes, the images will get pulled apart, creating an ugly gap. We need to make an arbitrary judgment about the amount of expansion we’ll accommodate. How large do we think the object might grow as text is resized in the browser? Realistically, we should account for the possibility of our tab text increasing by at least 300%. We need to expand the background images to compensate for that growth. For these examples we’ll make the back image (right-side) 400×150 pixels, and the front image 9×150 pixels.

Keep in mind that background images only show in the available “doorway” of the element to which they’re applied (content area + padding). The two images are anchored to the outside corners of their respective elements. The visible portions of these background images fit together inside the doorway to form a tab-like shape:

[Diagram shows both images with extra height added to the bottom. The right-side image also has extra width added to the left. The only portions which remain visible fit together perfectly to form the illustion of a tab-like shape.]

If the tab is forced to a larger size, the images slide apart, filling a wider doorway, revealing more of each image:

[Diagram shows the two images pulled apart slightly to create a wider tab, as well as a slightly taller vertical height to reveal more of each image. Since both background images have allowances for expansion, the the illusion is that the tab itself expanded naturally with the text contained inside.]

For this example, I used Photoshop to create two smooth, slightly three-dimensional, custom tab images shown at the beginning of this article. For one of the tabs, the fill was lightened and the border darkened — the lighter version will be used to represent the “current” tab. Given this technique’s model for left and right tab images, we need to expand coverage area of the tab image, and cut it into two pieces:

[Left- and right-side images]

The same thing needs to happen with the lighter current tab image. Once we have all four images created, (1, 2, 3, 4) we can jump into the markup and CSS for our tabs.

Tab Creation

As you explore the creation of horizontal lists with CSS, you’ll notice at least two methods for arranging a group of items into one row. Each comes with its own benefits and drawbacks. Both require dealing with rather funky aspects of CSS which quickly become confusing. One uses the inline box, the other uses floats.

The First Method — and possibly the more common — is to change the display of each list item to “inline”. The inline method is attractive for its simplicity. However, the inline method causes a few rendering problems in certain browsers for the Sliding Doors technique we’re going to discuss. The Second Method, which is the one we’ll focus on, uses floats to place each list item in a horizontal row. Floats can be equally frustrating. Their seemingly inconsistent behavior circumvents all natural logic. Still, a basic understanding of how to deal with multiple floated elements, and the means to reliably “break out” of floats (or contain them) can achieve wonders.

We’re going to nest several floated elements within another containing floated element. We do this so that the outer parent float completely wraps around the floats inside. This way, we’re able to add a background color and/or image behind our tabs. It’s important to remember that the next element following our tabs needs to reset its own position by using the CSS clear property. This prevents the floated tabs from affecting the position of other page elements.

Let’s begin with the following markup:

  <div id="header">
    <ul>
      <li><a href="#">Home</a></li>
      <li id="current"><a href="#">News</a></li>
      <li><a href="#">Products</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </div>

In reality, the #header div might also contain a logo and a search box. For our example, we’ll shorten the href value in each anchor. Obviously, these values would normally contain file or directory locations.

We begin styling our list by floating the #header container. This helps ensure the container actually “contains” the list items inside which will also be floated. Since the element is floated, we also need to assign it a width of 100%. A temporary yellow background is added to ensure this parent stretches to fill the entire area behind the tabs. We also set some default text properties, ensuring everything inside will be the same:

  #header {
    float:left;
    width:100%;
    background:yellow;
    font-size:93%;
    line-height:normal;
    }

For now, we also set all of the default margin/padding values of the unordered list and list items to “0”, and remove the list item marker. Each list item gets floated to the left:

  #header ul {
    margin:0;
    padding:0;
    list-style:none;
    }
  #header li {
    float:left;
    margin:0;
    padding:0;
    }

We set the anchors to block-level elements so we can control all aspects without worrying about the inline box:

  #header a {
    display:block;
    }

Next, we add our right-side background image to the list item (changes/additions are bolded):

  #header li {
    float:left;
    background:url("norm_right.gif")
      no-repeat right top;
    margin:0;
    padding:0;
    }

Before adding the left-side image, we pause so we can see what we have so far in Example 1. (In the example file, ignore the rule I’ve applied to the body. It only sets up basic values for margin, padding, colors, and text.)

- - -

Now we can place the left-side image in front of the right by applying it to the anchor (our inner element). We add padding at the same time, expanding the tab and pushing the text away from the tab edges:

  #header a {
    display:block;
    background:url("norm_left.gif")
      no-repeat left top;
    padding:5px 15px;
    }

This gives us Example 2. Note how our tabs have begun to take shape. At this point, a word of acknowledgement to confused IE5/Mac users, who are wondering, “What’s going on here? The tabs are stacked vertically and stretch across the entire screen.” Don’t worry, we’ll get to you soon. For now, do your best to follow along, or temporarily switch to another browser if one is handy, and be assured we’ll fix the IE5/Mac issue shortly.

- - -

Now that we have the background images in place for normal tabs, we need to change the images used for the “current” tab. We do this by targeting the list item which contains id="current" and the anchor inside it. Since we don’t need to alter any other aspects of the background, other than the image, we use the background-image property:

  #header #current {
    background-image:url("norm_right_on.gif");
    }
  #header #current a {
    background-image:url("norm_left_on.gif");
    }

We need some kind of border along the bottom of our tabs. But applying a border property to the parent #header container won’t allow us to “bleed” the current tab through this border. Instead, we create a new image with the border we want included along the bottom of the image. While we’re at it, we also add a subtle gradient so it looks like this:

We apply that image to the background of our #header container (instead of the yellow color we had), push the background image to the bottom of the element, and use a background color matching the top of this new image. At the same time, we remove the padding from the body element I originally inserted for us, and apply 10 pixels of padding to the top, left, and right sides of the ul:

  #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;
    }

To complete the tab effect, we need to bleed the current tab through the border, as mentioned above. You might think we would apply bottom borders to our tabs matching the border color in the #header background image we just added, then change the border color to white for the current tab. However, doing this would result in a tiny “step” visible to pixel-precision eyes. Instead, if we alter the padding of the anchors, we can create perfectly squared-off corners inside the current tab, as the magnified example below shows:

[Enlargement of two tab versions, the first showing the tiny 1-pixel step from using the bottom border, the second showing a perfect 90-degree angle.]

We do this by decreasing the bottom padding of the normal anchor by 1 pixel (5px - 1px = 4px), then adding that pixel back to the current anchor:

  #header a {
    display:block;
    background:url("norm_left.gif")
      no-repeat left top;
    padding:5px 15px 4px;
    }
  #header #current a {
    background-image:url("norm_left_on.gif");
    padding-bottom:5px;
    }

The change allows the bottom border to show through for normal tabs, but hides it for the current tab. This brings our code up to Example 3.

Finishing Touches

Keen eyes may have noticed white tab corners showing up in the previous example. These opaque corners are currently preventing the image in the back from showing through the left corner of the image in front. In theory, we could attempt to match the corners of the tab images with a portion of the background behind them. But our tabs can grow in height, which pushes the background behind them lower, shifting the background color we tried to match. Instead, we change the images, making the corners of our tabs transparent. If the curves are anti-aliased, we matte the edges to an average of the background color behind them.

Now that the corners are transparent, a piece of the right-side image shows through the corner of the left-side image. To compensate for this, we add a small amount of left padding to the list item equivalent to the width of the left-side image (9px). Since padding was added to the list item, we need to remove that same amount from the anchor to keep the text centered (15px - 9px = 6px):

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

However, we can’t leave it at that either, because our left-side image now gets pushed away from the left tab edge by the 9 pixels of padding we just added. Now that the inner edges of the left and right visible doorways butt up against each other, we no longer need to keep the left image in the front. So we can switch the order of the two background images, applying them to opposite elements. We also need to swap the images used for the current tab:

  #header li {
    float:left;
    background:url("left.gif")
      no-repeat left top;
    margin:0;
    padding:0 0 0 9px;
    }
  #header a, #header strong, #header span {
    display:block;
    background:url("right.gif")
      no-repeat right top;
    padding:5px 15px 4px 6px;
    }
  #header #current {
    background-image:url("left_on.gif");
    }
  #header #current a {
    background-image:url("right_on.gif");
    padding-bottom:5px;
    }

Once we do this, we arrive at Example 4. Note that the tweaks required to make the corners transparent creates a small dead space on the left side of the tab where it’s not clickable. The dead space is outside the text area, but it is slightly noticeable. Using transparent images for each side of our tabs is not required. If we prefer not to have the small dead space, we need to use a flat color behind the tabs, then use this color in the corner of our tab images instead of making them transparent. We’ll keep the new transparent corners for now.

- - -

For the remaining tweaks, we make a slew of changes all at once: bold all tab text, change normal tab text to a brown color, make current tab text a dark gray color, remove link underlines, and change the text color for the link hover state to the same dark gray. We see all additions and changes so far represented in Example 5.

One Hack for Consistency

After Example 2, we acknowledged a problem with IE5/Mac where each tab stretched across the entire browser width, forcing each one to stack vertically on top of each other. Not quite the effect we were intending.

In most browsers, floating an element will act sort of like shrink-wrapping it — it gets shrunk to the smallest possible size of the contents it contains. If a floated element contains (or is) an image, the float will shrink to the width of the image. If it contains only text, the float will shrink to the width of the longest non-wrapping line of text.

A problem enters the picture for IE5/Mac when an auto-width block-level element is inserted into a floated element. Other browsers still shrink the float as small as possible, regardless of the block-level element it contains. But IE5/Mac doesn’t shrink the float in this circumstance. Instead, it expands the float and block-level element to full available width. To work around this problem, we need to float the anchor also, but only for IE5/Mac, lest we throw off other browsers. First we’ll set the existing rule to float the anchor. Then we’ll use the Commented Backslash Hack to hide a new rule from IE5/Mac which removes the float for all other browsers:

  #header a {
    float:left;
    display:block;
    background:url("right.gif")
      no-repeat right top;
    padding:5px 15px 4px 6px;
    text-decoration:none;
    font-weight:bold;
    color:#765;
    }
  /* Commented Backslash Hack
     hides rule from IE5-Mac \*/
  #header a {float:none;}
  /* End IE5-Mac hack */

IE5/Mac browsers should now display the tabs as intended, according to Example 6. Nothing should have changed for non-IE5/Mac browsers. Note that IE5.0/Mac suffers from a lot of rendering bugs that were fixed in the upgrade to IE5.1. Because of this, the Sliding Doors technique suffers in version 5.0 beyond a point I’m willing to hack. Since the upgrade to IE5.1/Mac has been readily available for some time now, the percentage of OS 9 Macs still running IE5.0 should be tapering off to almost nothing.

Variations

We just walked through the Sliding Doors technique for creating tabbed navigation with pure text, marked up with an unordered list of links, altered with a few custom styles. It loads fast, is simple to maintain, and text within can be scaled up or down significantly in size without breaking the design. Need we mention how flexible the technique can be for creating any type of sophisticated-looking navigation?

Use of this technique is only limited by our imagination. Our final example represents just one possibility. But we shouldn’t let an example place boundaries on our ideas.

For instance, tabs aren’t required to be symmetrical. I quickly created Version 2 of these tabs, which avoids the shaded 3-D look in favor of flat colors, angular edges, and a wider and more detailed left-side. We can even switch the order of left/right images, depending on the design, as Version 2 shows. With some careful planning and clever image manipulation, the bottom border could be abandoned in favor of matching the tab images with the background running behind them, as shown in my Deco-inspired Version 3. If your browser supports alternate style sheet switching, you can even view this master file, and switch between the three different versions by alternating between style sheets.

Other effects we don’t cover here could be added on top of this technique. In the example I ran through, I changed the text color for the hover state, but entire images could be swapped out to create interesting rollover effects. Wherever two nested HTML elements already exist in the markup, CSS can be used to layer background images for effects we haven’t even begun to imagine yet. We created a horizontal row of tabs in this example, but Sliding Doors could be used in a many other situations. What can you do with it?

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.