9.8.12

A Detailed Look at the z-index CSS Property | Impressive Webs

A Detailed Look at the z-index CSS Property | Impressive Webs



Z-Index Property
Most CSS properties that a web developer deals with regularly are instantaneous in their application to elements on the page. For example, when you add the background-color or font-size property to an element on your page, in most cases you will see the results immediately upon page refresh. But other CSS properties are not quite as “plug and play” as we would like.

The z-index property is one example of the latter. I would venture to guess that z-index is probably the CSS property that is more speedily abandoned than any other. Very often — when I previously didn’t understand z-index — I would try to apply it to an element, hoping that the element would automatically “jump” to the top in the page’s stacking order. But that didn’t happen, so I would abandon that method and try some other way to solve the problem. Maybe you’ve had the same experience. Hopefully this article will clear up some misunderstandings regarding z-index.


What Exactly Does It Do?

Basically, the z-index property sets the stack order of an element. An element with greater stack order is always in front of another element with lower stack order. That over-simplified definition is exactly why beginning CSS developers often use z-index incorrectly.
The natural stacking order of a web page’s elements is decided by the order in which the elements appear in the page’s markup. Let’s provide a simple example that we can use to explain stacking order and how z-index can be used correctly (and incorrectly):
  1. <div id="header">  
  2. <p>This is the header</p>  
  3. </div>  
  4.   
  5. <div id="article">  
  6. <p>This is an article</p>  
  7. </div>  
  8.   
  9. <div id="footer">  
  10. <p>This is the footer.</p>  
  11. </div>  


Used When Elements Overlap One Another

In the above markup, we have three <div> elements (header, article, and footer), one after another. Let’s say our page design required that the header overlapped the top portion of the article by 10 pixels, and the article element overlapped the footer element by 10 pixels.
To see what I’m talking about, here is an example page with the markup above, and a background colour and 3px coloured border applied to each of the elements, so they can be easily distinguished from one another:

3 elements displayed normally

Now, let’s look at the same page, with a negative top margin applied to all three elements:

The same 3 elements with a negative top margin

Since we’ve applied the negative margin, we can now physically see the default stacking order in action. The “article” element overlaps the “header” element for the simple reason that the “article” appears after the “header” in the markup. And the same applies for the “footer”, and why it overlaps the “article”.

Resolving a Stacking Order Problem Without Z-Index

That example shows us that z-index is not the only solution to a “stacking order” problem. Sometimes, you can resolve such an issue by simply changing the order of elements in your HTML, then positioning them accordingly.

Attempting to Implement Z-Index

But let’s say we want those 3 elements to remain exactly where they are, and, for one reason or another, could not rearrange the elements in the markup. But we needed the overlap to be reversed: we want the header to overlap the article, and the article to overlap the footer. In our CSS, let’s apply z-index values to the elements and see what happens:
The CSS now looks like this:

  1. #header {  
  2.     backgroundblue;  
  3.     bordersolid 3px pink;  
  4.     z-index: 3;  
  5. }  
  6.   
  7. #article {  
  8.     backgroundred;  
  9.     bordersolid 3px purple;  
  10.     z-index: 2;  
  11. }  
  12.   
  13. #footer {  
  14.     backgroundgreen;  
  15.     bordersolid 3px yellow;  
  16.     z-index: 1;  
  17. }  
And here is the example page with those new styles added:

3 overlapping elements with z-index

Do you notice a difference? If you do, then you need to look again. There are no visual differences between that example and the previous one. View the source of the page, and you’ll see that, even though we’ve added a z-index value to each element, and ensured that the values represent a reverse stack order, it didn’t have any effect. Why not?

Why Doesn’t It Work?

The previously-referenced W3schools page provides the explanation. It says: “Z-index only works on elements that have been positioned (eg position:absolute;).”

In the example we’re using we can apply position: relative to our <div> selector (which will apply to all 3 elements), and the stacking order specified by our z-index values will instantly take effect. Here is the corrected demo page:

3 elements with z-index applied properly

The overlap is now reversed, because the z-index values have been used properly.

A Real-World, Practical Example

For an example of a good practical use for the z-index property, here is a site I coded that uses transparent PNGs for the tabbed navigation. First, each tab is inside of a list item with negative margins to make the tabs overlap. Next, each tab is given a specific z-index value, to reverse the natural stacking order. Then, a high z-index is applied to the “selected” tab to ensure that the stacking order is graphically visible. The CSS for those tabs would look something like this:

  1. ul#navigation li {  
  2.     positionrelative;  
  3.     margin-left: -24px;  
  4. }  
  5.   
  6. ul#navigation li.one {  
  7.     z-index: 5;  
  8. }  
  9.   
  10. ul#navigation li.two {  
  11.     z-index: 4;  
  12. }  
  13.   
  14. ul#navigation li.three {  
  15.     z-index: 3;  
  16. }  
  17.   
  18. ul#navigation li.four {  
  19.     z-index: 2;  
  20. }  
  21.   
  22. ul#navigation li.five {  
  23.     z-index: 1;  
  24. }  
  25.   
  26. ul#navigation li.selected {  
  27.     z-index: 100;  
  28. }  
The server-side code dynamically adds a class of “selected” to the currently selected tab, and the z-index for that tab is given a higher value than the rest. In this example I’ve used 100 which ensures that the “selected” item will still be on top even if more tabs are added later.

Some Notes to Keep in Mind About Z-Index

The z-index property affects the position of an element on the Z-axis, which refers to how an item is stacked perpendicular to the display (instead of Y-Axis and X-Axis which refer to elements positioned parallel to the display). The higher the z-index, the closer the element will be to the user.

In IE6, select elements always appear on top of all page elements, no matter what the z-index value of any element on the page. The best way to deal with select elements appearing over top of drop down menus and other elements, is to actually make the select element invisible using display: none via JavaScript when the overlapping element appears.
The z-index property generally takes an integer as a value, but can also accept values of inherit and auto, although those values do not work properly in all browsers.

In Internet Explorer versions 6 and 7, the stacking order of z-indexed elements is essentially “reset” for any elements that are contained by a positioned element, regardless of wether or not the container (or parent) has a z-index value set. In other words, an element with a z-index value of 100 will appear underneath an element with a z-index value of 1 if the former element is contained by a positioned parent, and the latter is not. This is an incorrrect implementation of the z-index property that has evidently been corrected in IE8.

To change the z-index value of an element with JavaScript, you would use the usual “camel casing minus the hyphen”, which is generally the norm for accessing CSS properties with JavaScript (e.g. myElement.style.zIndex = "100";).

Summary

In short, the z-index property can be a powerful tool when used correctly, and can offer a very easy solution to many layout issues in graphically complex designs. As long as you remember that it only applies to elements that have a value set for the position property, you will have no trouble using this interesting CSS property.