Z-Index And The CSS Stack: Which Element Displays First?

Steven Bradley

by Steven Bradley
on Wednesday, December 2nd, 2009
in CSS

«

»

Z-index is another css property that appears simple on the surface, but has some deeper rules that can cause confusion.

On the surface it may seem as simple as a positive z-index sits in front of a 0 z-index, which sits in front of a negative z-index. While that is true, there’s more to the overall equation about how a browser decides which elements display in front of others.

In last week’s post on css positioning I touched on the z-index property and mentioned it was more complex than my brief description allowed and that the details would be for another post. This is that more detailed post.

What is the Z-index?

Let’s start with a quick review. If you read the previous css positioning post you can probably skip to the next section.

A web page is a two dimensional plane with width and height. Z-index is the missing third dimension, depth, with an axis that moves in and out of your monitor. Z-index allows us to break out of the plane of the page and stack elements on top of each other.

z-index.png

A higher z-index moves toward the front of the page. It wants to reach out of the monitor and into your living room. A lower z-index recedes toward the back of the page away from your living room. If two elements are positioned to occupy the same space in the two dimensional plane and one has a z-index of 10 while the other has a z-index of 5, we would expect to see the z-index 10 element in front of the z-index 5 element.

The z-index property can take one of 3 values:

  • auto(default) Sets the stack order of the element to be equal to the stack order of the element’s parent.
  • number – Can be a positive number, a negative number, or 0. Sets the stack order for the element
  • inherit – Sets the z-index to the same as that of the parent element

The quick definitions of the values above are only so useful. To really understand what’s going on we need to discuss the stack.

sour like a stone
Creative Commons License photo credit: Demion

Stacking Contexts and Stacking Levels

Every css box has three dimensions along the horizontal, vertical, and z axis. When a browser is rendering your design elements along the z-axis it has to decide which element to draw on the canvas first. This order is described in terms of stacking contexts and stacking levels. You can think of a stacking level as being a new layer on the page, but what about this stacking context.

Stacking contexts can be a little confusing.

The root element (html) forms the root stacking context. Other stacking contexts are generated by any positioned element (including relatively positioned elements) having a computed value of ‘z-index’ other than ‘auto’. Stacking contexts are not necessarily related to containing blocks.

w3.org

Sure that’s clear.

The basic idea is there is one stacking context created by default with any web page. The root of that stacking context is the html element and elements inside that stacking context (everything inside the page) are located on different stacking levels within that default context.

When you add css positioning to an element and give it a z-index (other than auto) it creates new stacking context with new stacking levels inside the new context.

The z-index value creates a new integer stacking level for that element with a position along the z-axis set relative to the other boxes within the same stacking context.

Z-index is only one type of stacking level within a stacking context and the levels are rendered according to a set of stacking order rules, which will get to next.

More Water Bottle Caps
Creative Commons License photo credit: Incase Designs

Stacking Order

I know some (or maybe all) of the above discussion on stacking contexts and stacking levels is confusing. Hopefully you’re still with me, because the stacking order helps tie things together.

To understand the stacking order let’s build up the rules slowly by not considering z-index at all at first. In fact let’s look at only two levels in the stacking order to start and then see where new levels fit in the order

  1. Background and borders of the root element of the stacking context
  2. Descendant block boxes in the normal flow, in order of appearance (in the html)

stack-1.png

Remember the root of all root stacking contexts is the html element. Looking at the above you’ll see that the background and borders of the html element represent the lowest level of the stack. A css block box (a div inside your html for example) would be at a higher level within the stack.

Makes sense. If you add a background to your html and then fill a div with content inside your html, you’d expect the div content to be in front of the the html background.

Let’s start adding more levels to the stacking order

  1. Background and borders of the root element of the stacking context
  2. Descendant block boxes in the normal flow, in order of appearance (in the html)
  3. Descendant positioned elements, in order of appearance (in html)

stack-2.png

Positioned elements without z-index applied or z-index: 0 are on a higher stacking level than non-positioned elements. Even if you don’t specify a z-index (default becomes auto) your positioned element will appear on a higher layer than block level elements in the normal document flow.

  1. Background and borders of the root element of the stacking context
  2. Descendant block boxes in the normal flow, in order of appearance (in the html)
  3. Floating blocks
  4. Descendant positioned elements, in order of appearance (in html)

stack-3.png

Floated elements have a higher stacking level than block level elements in the normal document flow, but a lower stacking level than positioned elements without z-index applied.

  1. Background and borders of the root element of the stacking context
  2. Descendant block boxes in the normal flow, in order of appearance (in the html)
  3. Floating blocks
  4. Descendant inline boxes in the normal flow, in order of appearance (in the html)
  5. Descendant positioned elements, in order of appearance (in html)

stack-4.png

Notice that inline boxes have a higher stacking level than both block boxes and floated boxes, which you might not expect.

Now lets put the z-index back in and get the full stacking order rules as define by the w3C.

  1. the background and borders of the element forming the stacking context.
  2. the stacking contexts of descendants with negative stack levels. (negative z-index)
  3. a stacking level containing in-flow non-inline-level non-positioned descendants. (block level boxes in the normal document flow)
  4. a stacking level for non-positioned floats and their contents. (floated boxes)
  5. a stacking level for in-flow inline-level non-positioned descendants. (inline boxes)
  6. a stacking level for positioned descendants with ‘z-index: auto’, and any descendant stacking contexts with ‘z-index: 0′.
  7. the stacking contexts of descendants with positive stack levels. (positive z-index)

stack-5.png

A few things stand out in the final stacking order. As you might expect an element with a positive z-index appears at the top of the stack and while not specifically mentioned the higher the z-index the higher the level in the stack order.

What is less expected is that boxes with negative z-indexes are still higher in the stacking order than the background and borders of the element forming the stacking context. Remember that element forming the stacking context is likely the element you just added z-index to.

Also it’s interesting where boxes with a z-index of 0 or auto lie in the stacking order. There are several stacking levels below your z-index: 0 element, which you might not expect.

The main thing to understand about the stacking order is that more than the z-index value goes into determining what layer in the stack an element is on.

Browser Issues with the Stacking Order

In a perfect world we’d be done. It’s not a perfect world as you know and in the context of z-index it’s browsers that are imperfect. I mentioned two of these in my last post, but they bear repeating

1. Select boxes in IE6 – In IE6 a select box <select> will always appear at the top of the stack. You can set all the z-indexes you want, but the select box will still be at the top.

2. E6 and IE7 have another z-index issue with stacking context. IE looks to the outermost parent with positioning applied to determine which group of elements is at the top of the stack instead of looking at each individual element.

<div style="z-index: 0">
  <p style="z-index: 10"></p>
</div>
<img style="z-index: 5" />

You would expect the paragraph to be at the top of the stack, because it has the highest z-index. However IE6 and IE7 would place the image on top of the paragraph, because it sees two different stacks. One for the div and one for the image. The image has a higher z-index than the div and so will sit on top of everything inside the div.

3. Firefox 2 and negative z-index – FF is not immune from browser issues. Firefox 2 always places an element with a negative z-index behind the entire stacking context instead of above the background and borders of the root of the stacking context.

Summary

Z-index is a little more complex than it first appears. It gets even more complex when you try to explain it. I hope I didn’t confuse you in trying to explain how z-index works.

The main points to remember are that css uses stacking contexts and stacking levels within each of those stacking contexts. CSS also describes a stacking order for which level appears in front of or behind the others around it. Z-index accounts for 3 stacking levels, but there are other stacking levels as well.

By default your html element creates a stacking context and then each time you use css positioning and give the element a z-index you create a new stacking context with it’s own stacking levels and stacking order. While not too difficult to understand where one element will display inside one stacking context, it can be somewhat confusing when comparing different levels in different stacking contexts.

The more positive the z-index the more in front the element appears. The more negative the z-index the further away it appears. However other stacking levels are intertwined with the three z-index stacking levels.

If you’ve ever tried to use z-index and found things not quite working like you expected the answer to why is likely in the stacking order (or occasionally an imperfect browser)

Questions?

Spread some karma These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • Sphinn
  • del.icio.us
  • Mixx
  • StumbleUpon

Subscribe to TheVanBlog | Email This Post Email This Post

13 Responses to “Z-Index And The CSS Stack: Which Element Displays First?”

MyAvatars 0.2
2009-12-04 16:06:47

This article has been shared on favSHARE.net. Go and vote it!

 
MyAvatars 0.2
Diane
2009-12-09 07:52:21

Excellent article Steve! :)

MyAvatars 0.2
2009-12-09 23:16:14

Thanks Diane.

 
 
MyAvatars 0.2
Mark Spitz Subscribed to comments via email
2010-01-16 13:43:09

I think the point you make about errors with IE browsers may be misleading and here’s my understanding about why:

In the example snippet you provide, all browsers correctly place the image above the paragraph because the (with paragraph’s inside) and the image share the same stacking context. It’s as though there is a a parent enclosing all your code with any z-index value. The value doesn’t matter because this parent is setting the stacking context for ALL its descendants.

Okay, what we need then to demonstrate IE’s typically wayward behaviour is a real parent and let’s assume it is given a z-index of 69 (any old number will do).

If you leave the rest of your code snippet unchanged then all browsers will continue to place the image above the text.

But now remove the z-index from the div with the paragraph. This forces browsers to give that div the default value for z-index which is “auto”.

It is this that IE gets wrong. It treats auto as though it were a value of 1 and (crucially) also establishes a new stacking context. The div and the image now no longer share the same stacking context as far as IE is concerned. This leaves the image above the paragraph.

Standards compliant browsers will treat the auto attribute correctly meaning that it inherits the z-index of its parent and NO new stacking context is created. The result then is the text above the image.

Confusing isn’t it! And sometimes the act of trying to explain can confuse further. In case I have done that then try a simpler analysis to show IE’s mistreatment of “auto” and change the z-index value on your from zero to auto and check it out.

MyAvatars 0.2
2010-01-18 14:38:50

Thanks Mark. I’ll have to test some code across browsers. The code in the post is more from memory than testing so it’s always possible I got it wrong and your explanation does make a lot of sense.

I had thought the code I used would cause the problem, but now I’m thinking you’re right and it’s the z-index: auto being treated as z-index: 1 in IE that causes the problem. Maybe I was thinking more about the fix, which would be to increase the z-index on the div to be more than the z-index on the image. Of course that assumes it would still work like you want in other browsers.

It definitely gets confusing. You can read through the specs and even test different code and sometimes you still have no idea why something is happening.

 
 
MyAvatars 0.2
noone
2010-02-07 23:18:27

It may be worth mentioning that declaring position:static on an element does not register its z-index correctly.

MyAvatars 0.2
2010-02-08 17:39:12

Thanks for pointing that out. I wasn’t aware of the issue. Do you know if it’s specific to certain browsers or is it a general issue affecting all browsers?

As far as I know z-index should work the same on statically positioned elements. Should being the operative word. The spec says it should work at least.

If you can offer more details or point me somewhere that talks about this more it would be appreciated.

Thanks again.

 
 

What others are saying about this post

Tweets that mention Z-Index And The CSS Stack: Which Element Displays First? | Van SEO Design -- Topsy.com
uberVU - social comments
Z-Index And The CSS Stack: Which Element Displays First? | Van SEO Design » Web Design
Z-Index And The CSS Stack: Which Element Displays First? | favSHARE.net
Z-Index And The CSS Stack: Which Element Displays First? | Design Newz
110+ Incredible Community Links for Web Designers and Develovers | tripwire magazine


Name (required)
E-mail (required - never shown publicly)
URI
Your Comment

Subscribe

Search TheVanBlog

Recommended

Small Business Forum Teaching Sells Free Report

SEO Book Training

Popular Posts