为什么浏览器会在带有负数 z-index 的元素后面渲染 body?
Why does the browser render the body behind elements with a negative z-index?
我发现了一个奇怪的问题,当我渲染一个带有负数z-index(z-index: -1
)的元素的页面并调用document.elementsFromPoint
时,结果是视觉上元素负数 z-index
出现在 body 上方,但 elementsFromPoint
将元素置于 <html>
和 <body>
元素之间。
<html>
<head></head>
<body>
<main>
<h1>A title</h1>
</main>
<img src="foo.bar" alt="foo bar">
</body>
</html>
如果我应用 CSS 将图像移动到标题顶部,如下所示:
body {
background-color: #FFF;
}
img {
position: absolute;
}
然后我将从 elementsFromPoint
得到的 <h1>
下的堆栈将是:
<img>
<h1>
<main>
<body>
<html>
现在,如果我修改 CSS 使图像位于标题下:
body {
background-color: #FFF;
}
img {
position: absolute;
z-index: -1;
}
然后在视觉上,图像出现在标题下方,但仍出现在 <body>
上方。但是调用 elementsFromPoint
我现在得到:
<h1>
<main>
<body>
<img>
<html>
请注意,<img>
元素位于 <body>
和 <html>
元素之间。这是有道理的,因为 <body>
将具有 0
的默认 z-index
,因此 <img>
元素应呈现在其下方。
但如果是这样,为什么浏览器会在 <body>
上方呈现图像?我已经在 Chrome 和 Firefox 中检查过了,结果是一样的。
编辑: 下面是这种奇怪效果的演示。面包片都是<body>
标签的内容,另外两张图片夹在中间。
body {
background-image: url('https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/microsoft/209/bread_1f35e.png');
background-repeat: no-repeat;
font-size: 110px;
padding: 0.25em;
}
img {
position: absolute;
left: 10px;
top: 10px;
z-index: -1;
}
img + img {
top: 25px;
left: 25px;
}
<img src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/microsoft/209/herb_1f33f.png" alt="greens in the sandwich">
<img src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/microsoft/209/bacon_1f953.png" alt="meat between the bread">
首先,默认 z-index
是 auto
而不是 0
。这是有区别的,因为最后一个会创建一个堆栈上下文,使它里面的元素(即使有负 z-index
)总是在上面渲染。此处有更多详细信息:Why can't an element with a z-index value cover its child?
那么你面对的是background propagation,这是将背景颜色设置为body元素时的一种特殊行为,这会让你认为元素不在后面。
然后你的图片设置为 position:absolute
使其脱离流因此它不会影响 body 的高度所以即使它在后面我们仍然可以看到它。
这里有一些例子来说明不同的情况:
body {
position: relative;
background-color: #000;
}
img {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
}
h1 {
margin: 0;
background-color: rgba(255, 255, 255);
padding: 0.5em 1em;
text-align: center;
font-size: 2.5rem;
}
<main>
<h1>A polar bear</h1>
<pre>
</pre>
</main>
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Polar_Bear_AdF.jpg" alt="A Polar Bear">
在上面的背景中,背景从 body 传播到 html,图像在 body 后面渲染并且 body 高度等于 h1
.
让我们通过将背景设置为 html
来禁用传播
body {
position: relative;
background-color: #000;
}
html {
background:red;
}
img {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
}
h1 {
margin: 0;
background-color: rgba(255, 255, 255);
padding: 0.5em 1em;
text-align: center;
font-size: 2.5rem;
}
<main>
<h1>A polar bear</h1>
<pre>
</pre>
</main>
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Polar_Bear_AdF.jpg" alt="A Polar Bear">
现在更清楚了,我们有 html(红色),然后是图像,然后是 body(黑色)及其内容。您还可以看到 body 的高度受限于其 in-flow 内容。
现在让我们将 z-index:0
添加到 body:
body {
position: relative;
background-color: #000;
z-index:0;
}
html {
background:red;
}
img {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
}
h1 {
margin: 0;
background-color: rgba(255, 255, 255);
padding: 0.5em 1em;
text-align: center;
font-size: 2.5rem;
}
<main>
<h1>A polar bear</h1>
<pre>
</pre>
</main>
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Polar_Bear_AdF.jpg" alt="A Polar Bear">
body 现在正在创建一个堆栈上下文,强制在内部绘制图像,现在的顺序是 html 然后 body 然后是它的内容(图像然后是标题)
我发现了一个奇怪的问题,当我渲染一个带有负数z-index(z-index: -1
)的元素的页面并调用document.elementsFromPoint
时,结果是视觉上元素负数 z-index
出现在 body 上方,但 elementsFromPoint
将元素置于 <html>
和 <body>
元素之间。
<html>
<head></head>
<body>
<main>
<h1>A title</h1>
</main>
<img src="foo.bar" alt="foo bar">
</body>
</html>
如果我应用 CSS 将图像移动到标题顶部,如下所示:
body {
background-color: #FFF;
}
img {
position: absolute;
}
然后我将从 elementsFromPoint
得到的 <h1>
下的堆栈将是:
<img>
<h1>
<main>
<body>
<html>
现在,如果我修改 CSS 使图像位于标题下:
body {
background-color: #FFF;
}
img {
position: absolute;
z-index: -1;
}
然后在视觉上,图像出现在标题下方,但仍出现在 <body>
上方。但是调用 elementsFromPoint
我现在得到:
<h1>
<main>
<body>
<img>
<html>
请注意,<img>
元素位于 <body>
和 <html>
元素之间。这是有道理的,因为 <body>
将具有 0
的默认 z-index
,因此 <img>
元素应呈现在其下方。
但如果是这样,为什么浏览器会在 <body>
上方呈现图像?我已经在 Chrome 和 Firefox 中检查过了,结果是一样的。
编辑: 下面是这种奇怪效果的演示。面包片都是<body>
标签的内容,另外两张图片夹在中间。
body {
background-image: url('https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/microsoft/209/bread_1f35e.png');
background-repeat: no-repeat;
font-size: 110px;
padding: 0.25em;
}
img {
position: absolute;
left: 10px;
top: 10px;
z-index: -1;
}
img + img {
top: 25px;
left: 25px;
}
<img src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/microsoft/209/herb_1f33f.png" alt="greens in the sandwich">
<img src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/microsoft/209/bacon_1f953.png" alt="meat between the bread">
首先,默认 z-index
是 auto
而不是 0
。这是有区别的,因为最后一个会创建一个堆栈上下文,使它里面的元素(即使有负 z-index
)总是在上面渲染。此处有更多详细信息:Why can't an element with a z-index value cover its child?
那么你面对的是background propagation,这是将背景颜色设置为body元素时的一种特殊行为,这会让你认为元素不在后面。
然后你的图片设置为 position:absolute
使其脱离流因此它不会影响 body 的高度所以即使它在后面我们仍然可以看到它。
这里有一些例子来说明不同的情况:
body {
position: relative;
background-color: #000;
}
img {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
}
h1 {
margin: 0;
background-color: rgba(255, 255, 255);
padding: 0.5em 1em;
text-align: center;
font-size: 2.5rem;
}
<main>
<h1>A polar bear</h1>
<pre>
</pre>
</main>
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Polar_Bear_AdF.jpg" alt="A Polar Bear">
在上面的背景中,背景从 body 传播到 html,图像在 body 后面渲染并且 body 高度等于 h1
.
让我们通过将背景设置为 html
body {
position: relative;
background-color: #000;
}
html {
background:red;
}
img {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
}
h1 {
margin: 0;
background-color: rgba(255, 255, 255);
padding: 0.5em 1em;
text-align: center;
font-size: 2.5rem;
}
<main>
<h1>A polar bear</h1>
<pre>
</pre>
</main>
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Polar_Bear_AdF.jpg" alt="A Polar Bear">
现在更清楚了,我们有 html(红色),然后是图像,然后是 body(黑色)及其内容。您还可以看到 body 的高度受限于其 in-flow 内容。
现在让我们将 z-index:0
添加到 body:
body {
position: relative;
background-color: #000;
z-index:0;
}
html {
background:red;
}
img {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
}
h1 {
margin: 0;
background-color: rgba(255, 255, 255);
padding: 0.5em 1em;
text-align: center;
font-size: 2.5rem;
}
<main>
<h1>A polar bear</h1>
<pre>
</pre>
</main>
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Polar_Bear_AdF.jpg" alt="A Polar Bear">
body 现在正在创建一个堆栈上下文,强制在内部绘制图像,现在的顺序是 html 然后 body 然后是它的内容(图像然后是标题)