Why doesn't the z-index style apply to the <body> element?

Peter Olson picture Peter Olson · Aug 20, 2015 · Viewed 8.4k times · Source

The z-index style allows you to control what order boxes are painted in. For example, you can make a child element be painted below its parent element:

However, when the parent element is the <body> tag, this no longer behaves as expected:

body {
  background: rgba(33, 33, 33, 0.7);
}
#child {
  width: 100px;
  height: 100px;
  background: yellow;
  position: relative;
  z-index: -1;
}
<body>
  <div id="child"></div>
</body>

The CSS specification §9.9.1 states (emphasis mine):

The root element 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. In future levels of CSS, other properties may introduce stacking contexts, for example 'opacity' [CSS3COLOR].

Within each stacking context, the following layers are painted in back-to-front order:

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

If <body> were the root element, then this behavior would make sense, since that would mean that the <body> element is always painted first no matter what.

However, in an HTML document, <html> is the root element. Given that, why can't we place an element under <body> with the z-index style?


(This question was motivated by a similar question on the Russian Stack Overflow site.)

Answer

Shaunak picture Shaunak · Aug 20, 2015

<body> tag's default positioning is static. And by definition static positioning means ignore all positioning instructions.

In other words because z-index property does not apply to elements that have position:static, it does not apply to body as it's position defaults to static

Here's a good discussion on why z-index does not work on position:static

Update: So why doesn't it work with body { position:relative } ?

Because body get's a stacking context. Now with z-index, a element can only go behind or forward relative to its siblings but never behind its parent. Because body is a parent element, setting negative z-index on it's child does not take it behind body.