An often-discussed advancement in CSS is the ability to stack background images, allowing them to slide on top of each other to create special effects. According to the current rules of CSS 2.0, each background image requires its own HTML element. In many cases, the typical markup already provides a variety of elements for us to use as general interface components.
With simple design, we can do it.
Where does the innovation come from?
Many CSS-based navigation tags I have seen mostly have the same characteristics: a rectangular color block, maybe just an outline, no border for the currently selected tag, and the tag changes color when the mouse pointer moves over it. Is this all CSS can give us? A series of little boxes and drab colors?
Before CSS was widely adopted, we had seen many innovations in tab navigation design. Original form, expert color mixing, and imitation of many physical interfaces in the real world. But these designs often rely too much on complexly crafted images with text, or are packaged into nested tables. Modifying text or changing the order of labels requires a complex process. It is even impossible to stretch the text, or it will greatly affect the layout of the page.
Text-only navigation bars are more durable and load faster than text-as-image navigation bars. Similarly, we can even add alt attributes to each image. For those with low vision, plain text can be resized freely. Not surprisingly, plain text-based navigation bars, styled with CSS, are back in web design. However, most CSS-based navigation bar designs are still meaningless so far. A recently adopted technology (such as CSS) can allow us to do better, without losing the effect of those table and image tags mentioned earlier.
sliding door technology
Beautiful craftsmanship, truly flexible interface components, and adaptive sizing based on the text, we can create it with two independent background images. One on the left and one on the right. Think of these two images as two sliding doors that slide together and overlap to occupy a narrower space, or slide apart from each other to occupy a wider space, as shown in the following image:
In this model, one image masks part of another image. Suppose we place some unique content around each image, such as rounded corners for labels. We don't want the top image to completely obscure the bottom one. To prevent this from happening, we can make the image above (the one on the left in this example) as narrow as possible. But still ensure a certain width to show the uniqueness of one side of the label. If the outer corners are rounded, we should control the above image to have the same width as its arc part.
If the target grows in size and exceeds the width shown above, the image will be stretched apart due to changes in text size and font, creating unsightly gaps. What we need to judge is predicting how much this scalability will be. If I change the font size in the browser, will the target grow? Practically speaking, we should at least estimate the font size to increase to 300%. Background images also have to accommodate this growth. For the above example, we set the lower (right) image to 400*150 pixels and the upper image to 9*150 pixels.
If the label is stretched, the image slides away, the doorway becomes wider, and more of the image is revealed:
In this example, I made two smooth, thin 3D label images in photoshop, as shown at the beginning of the article. For one, the interior is bright and the border is darker to represent the currently selected label. To apply this trick model to the left and right images, we need to expand the area covered by the label image and crop it into two parts:
The same approach will apply to the label called "current". Once we have these four images (1, 2, 3, 4) we can start making our labels with markup and CSS.
creation of labels
When you look into using CSS to create horizontal lists, you'll find that there are at least two ways to arrange list items on the same row. Both methods have their own merits, but both require CSS to solve the confusion caused by layout. One method uses inline boxes, the other uses floats.
Method one, which may be a more common one, is to display all list items inline. The beauty of the inline approach lies in its simplicity. However, for the sliding door technology we are about to talk about, the inline method has some interpretation problems on specific browsers. Method two, which we will focus on, is to use floats to arrange list items in the same row. Frustratingly, the seemingly contradictory behavior of floats happens to evade natural logic. Still, the basic understanding of how to deal with multiple floating elements, and what reliable floating means, is worth discussing.
We will use another type of floating element to solve the problem of floating element arrangement. In this way, the parent element completely encompasses the child element. Therefore, we can add background color and background image to the label. It is very important to remember that text elements immediately following the label use the clear function in CSS to clear floating objects. This prevents floating labels from affecting the position of other elements on the page.
We start 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 may also contain the logo and search box. For our example, we want to shorten the value of each hyperlink in the anchor chain. Obviously, these values should correctly contain the location of the file or directory.
We start designing the list by positioning the #header container. This ensures that the container actually acts as a container to contain the list items floating inside it. Since the element is floated, we also need to declare its width to be 100%. Add a temporary yellow background to ensure that the parent container completely fills the entire area behind the label. Likewise, set the default text properties to ensure uniform styling:
#header {
float:left;
width:100%;
background:yellow;
font-size:93%;
line-height:normal;
}
Now, we also need to set the default margin/padding value for the unordered list to 0, and remove the mark in front of the list item. Each list item floats left:
#header ul {
margin:0;
padding:0;
list-style:none;
}
#header li {
float:left;
margin:0;
padding:0;
}Set the anchor chain to force rendering as a block object, and we can control all styles without worry:
#header a {
display:block;
}
Next, we add the background image on the right to the list item (changes shown in bold):
Now we can position the left image to the left of the anchor chain (the element inside the container). We also add padding, which enlarges the label and pushes the text away from the edges of the label:
#header a {
display:block;
background:url("norm_left.gif")
no-repeat left top;
padding:5px 15px;
}
In this way we get effect 2. Notice how our label is shaped. Here, IE5/Mac users will immediately be surprised, "Oh my God, my tabs are stacked vertically and extend to the entire screen!" Don't worry, we will help you solve it right away. For now, try to follow the steps below, or if convenient, temporarily switch to another browser, and the problem with the IE5/Mac version will be solved immediately.
Now that the background image for the general label is complete, we need to replace the image for the "current" label. We achieve this by adding id="current" and an anchor chain to the target list item. Since there is no need to change the appearance of the background other than the image, we use the background-image feature:
We place the image into the background of the #header container (replacing the original yellow background), move the background image to the bottom, and add the corresponding background color to the blank space above the image. At the same time, remove the padding inherited from body and add 10 pixels of padding to the top, left and right sides of 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;
}
We do this by reducing the bottom padding value of the normal anchor chain by 1 pixel (5px-1px=4px), and then adding the subtracted padding to the "current" anchor chain.
finishing touches
Keen observers may have noticed the white label corners in the previous example. These opaque corners are used to prevent the image below from showing through to the one above. In theory, we could try to use part of the background image to fit the label's background. But our label will grow in height. If we try to move the background color, the background image will become shorter. Instead, change the image so that the corners of the label are transparent. If the arc is anti-aliased, we use a more even background color around its edges.
Now that the corners have become transparent, the image on the left will show through the corners of the image on the right. To compensate, we add padding (9px) to the form item that matches the width of the image on the left. Now that we have added padding to the form item, we need to remove the same width to center the text (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;
}
It's not over yet, because the addition of 9 pixels of padding creates a gap between the left image and the left side of the label. Now that the left and right edges of the visible "doorway" are connected, we no longer need to keep the left image on top. So, swap the order of the two background images and reverse them. Also swap the two images used in the "current" tag:
#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;
}
After completing this, we arrive at Effect 4. Note that the transparent corners create a non-clickable area on the left side of the label. This area is outside the text, but still perceptible. It is not necessary to use transparent images on both sides of the label. If we don't want to create this invalid area, then we have to use a color behind the label and then replace the transparent image in the corners of the label with this color. Now we just keep this transparent corner.
For the rest of the problem, we'll make all the changes at once: make the label text heavier, change the text in the normal label to brown, change the "current" label text to dark gray, remove the underline of the link, and finally change the hover text color Changed to the same dark gray color. After a series of changes, we'll look at the effect so far 5.
Consistent solution
After Effect 2, one problem we recognized is that in IE5/Mac browsing mode, each tab extends and occupies the entire width of the browser, so that tabs are stacked vertically together. This is not what we want.
In most browsers, a floating element shrinks to a minimum size of its containing content. If a floated element contains an image or is an image, it shrinks to the width of the image. If it contains only text, it will shrink to the width of the longest, non-topped text.
A problem occurs in images in IE5/Mac when an auto-width block object element is inserted into a floated element. Other browsers still minimize floats and ignore block elements within the container. But IE5/Mac does not follow this behavior, instead it expands float and block object elements to as wide as possible. To solve this problem, we will float the anchor chain at the same time, but only for IE5/Mac, so as not to give up other browsers. First, we set the floating rules for the anchor chain. Then, we use the backslash comment method to hide this rule so that it only takes effect for IE5/Mac and ignores other browsers:
Draw inferences from one example We just practiced the sliding door technique, using plain text and an unordered list to create navigation labels, with a small amount of styling. It loads quickly, is maintainable, and the size of the text can be greatly expanded without ruining the appearance. We need not reiterate the flexibility of sliding door technology in creating complex styles of navigation bars.
There is nothing you can't think of and nothing you can't do. The final effect shows us an example, but our design cannot be limited by this.
In some cases, labels are not necessarily symmetrical. I quickly made a second version of this label, also with a shaded 3D style, angular edges, and a distinctive left part. According to the second version, we can even swap the positions of the left and right images. With this detailed layout and smart image control, we can remove the bottom border of the button so that the label image fits better into the background, as shown in the third version. If your browser supports switching between multiple style sheets, you can even use it to freely switch between multiple versions of the navigation bar.
There are many other effects that we haven't mentioned. A quick note, I changed the color of the text on mouseover, but the entire image could be replaced to create a more interesting transformation effect. Even if there are two nested HTML elements in the markup, CSS can be used to achieve some effects that we have not yet thought of. What we created in this example is just a horizontal tab bar, but sliding doors can be used in many other situations. What do you think?