为什么 z-index 样式不适用于 <body> 元素?

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

z-index 样式允许您控制绘制顺序框的位置。例如,您可以将子元素绘制在其父元素下方:

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

然而,当父元素是 <body> 标签时,这不再像预期的那样运行:

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 状态(强调我的):

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).

如果 <body> 是根元素,那么这种行为是有道理的,因为这意味着 <body> 元素无论如何总是先绘制。

但是,在 HTML 文档中,<html> 是根元素。鉴于此,为什么我们不能在 <body> 下放置一个具有 z-index 样式的元素?


(这个问题的动机是similar question on the Russian Stack Overflow site。)

<body> 标签默认位于堆栈底部。它根本无法设置,因为它始终是可能的最低值。

来源:Adobe Forums

<body> 标签的 default positioningstatic。并且根据定义,静态定位意味着忽略所有定位指令

换句话说,因为 z-index 属性 不适用于具有 position:static 的元素,它不适用于 body,因为它的位置默认为 static

这里有一个很好的 discussion 说明为什么 z-index 在 position:static

上不起作用

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

因为 body 得到一个 stacking context。现在有了 z-index,一个元素只能相对于它的 siblings 落后或前进,而不能落后于它的父元素。因为 body 是一个 parent 元素,所以在它的子元素上设置负的 z-index 不会把它放在 body 后面。

好吧,关于这个的文档不多。

但是 <body> 标签不能有任何兄弟标签,所以为什么需要更改它的 z-index?

它甚至被认为是 'positioned' 元素吗?

您可以随心所欲地使用它的子元素 z-index 并在任何情况下获得想要的结果,没有必要无缘无故地将 html 与 css 样式过度复杂化全部

很难找到关于这个问题的官方文档,甚至是权威文档,可能是因为它不是现实生活中常见的场景,但 Ian Hickson 之前已经讨论过这个问题Tantek CelikCSS Specification.

的编辑

下面是 thread from a W3C mailing list 的一些部分,规范编写者在其中讨论 z-indexbody 元素相关的行为。

讨论的实质是这样的:

  • 浏览器忽略非定位元素(如body)的z-index是正确的,因为z-index只适用于定位元素

  • 由于 stacking contexts

    的创建,元素的
  • 的 z 索引仅与兄弟元素相关,与父元素无关

    ... a child box cannot circumvent the z-order of its parent. it can place itself behind or in front of any of its siblings, but it cannot place itself behind it's parent box. it can place itself in such a way that it is first child rendered before any other child ....

  • 关于 z-indexposition: fixedbody 元素上的行为还有一个有趣的注释,但它 doesn't look like it was implemented.


Tantek Celik:

I've got a question regarding the z-index property: Why can I still see elements which I've put behind the BODY element (see example below)?

Because your browser has a bug or doesn't support z-index.

Or the browser doesn't have a bug and is properly ignoring z-index on non-positioned elements.

<BODY STYLE="z-index: 0; background-color: #456789;">
<P STYLE="z-index: -1; color: #fedcba;">This is a test showing a text that shouldn't be visible as it lies behind the body element <EM>("z-index" property equals "-1").</EM>
</BODY>

In the example given, both elements which have a z-index do not have their position property set, and since according to:

http://www.w3.org/TR/REC-CSS2/visuren.html#z-index

the z-index property "Applies to: positioned elements", the settings on the z-index property are ignored.

Tantek

规范作者的回复:

hi,

(Tantek: i do agree with you that the spec says z-index is only for positioned elements, but as Ian says, i don't see why it cannot be applied for static boxes which overlap due to negative margins.)

look at the following markup:

<body style="z-index=0; background-color=green;">
<p style="z-index=-1; position: relative; top: 50; left: 20"> hello!! </p>
<p> world!! </p>
</body>

P is a child of BODY, and according the CSS2 spec (my reading, anyway :) z-indexing of an element is relative only to sibling elements, and not to parent elements. this has to do with the creation of a z-index contexts.

so the box for 'hello!!' would show up behind the box for 'world!!' but NOT behind the box for BODY because BODY contains both P element boxes.

!!! please correct if i'm wrong on this, because if i am, i have to redo my renderer so that it does not respect hierarchical boundaries, which is NOT a happy situation. !!!

the original intent of this thread (the question) can be attained by making the z-index=-1 box a position: fixed box (though the positioning properties would be complex.) this would work because fixed boxes break out of the hierarchy where they are found and levitate to the viewport box, essentially becoming a sibling to the BODY box.

-- ranjit

规范作者:

please,

pardon my use of implementation specific terms.

you are correct about the HTML assumption. but my point remains valid, even if we look at the hierarchy of the document/box structure regardless of markup.

currently, in my implementation, the following implicit rule is dictated by the hierarchical structure of the boxes generated by parsing a hierarchical document structure (XML, HTML, ...)

RULE: a child box cannot circumvent the z-order of its parent. it can place itself behind or in front of any of its siblings, but it cannot place itself behind it's parent box. it can place itself in such a way that it is first child rendered before any other child, ....

i see this rule implied by the CSS2 spec as well, in the section where there is talk of z-order contexts and so on.

as i see it, z-order values for a CHILD boxes are valid within the parent z-order context. this can be illustrated with absolute positioned boxes containing absolute positioned boxes where a child absolute boxes have a z-ordering that cannot violate the z-ordering of the parent absolute boxes.

again, let me say: if i have misunderstood something in the spec, let me know, for if the above rule is invalid, then it seems to me the notion of hierarchy is not preserved for non-fixed boxes.

regards,

-- ranjit

http://lists.w3.org/Archives/Public/www-style/1999Aug/0131.html

这里的问题是,如果 html 元素没有指定背景,canvas 会采用 body 元素的背景,并首先绘制。 CSS 2.1 says:

For documents whose root element is an HTML "HTML" element or an XHTML "html" element that has computed values of 'transparent' for 'background-color' and 'none' for 'background-image', user agents must instead use the computed value of the background properties from that element's first HTML "BODY" element or XHTML "body" element child when painting backgrounds for the canvas, and must not paint a background for that child element.

看看当 html 元素被赋予背景时会发生什么:

html { 
  background-color: white;
}

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>