子元素带有不透明度时,不能出现在父元素的具有 z-index 的兄弟元素下方。

4

我试图理解为什么将一个元素的子元素的不透明度设置为1之外的值会使其始终位于该元素兄弟元素的顶部。

.element {
  width: 500px;
  height: 100px;
  background: orangered;
}

.child {
  height: 150px;
  width: 100px;
  background: grey;
  
  opacity: 0.5;
  z-index: 1;
}

.sibling {
  width: 400px;
  height: 100px;
  background: skyblue;
  
  z-index: 2;
}
<div class="element">
  <div class="child"></div>
</div>
<div class="sibling"></div>

移除透明度属性(或将其设置为1)的.child使其按预期位于.sibling后面,但是对于某些原因,其他不同于此值的不透明度会改变它们的堆叠顺序。这让我认为.element在某种程度上形成了一个堆叠上下文,但据我所知,它没有满足MDN 网站上的任何标准。

根据我所理解的,CSS 标准没有关于此问题的说明:

由于透明度小于1的元素是由单个离屏图像合成的,因此它之外的内容不能在其内部的内容之间以z轴顺序堆叠。出于同样的原因,实现必须为任何透明度小于 1 的元素创建一个新的堆叠上下文。如果透明度小于 1 的元素未定位,则它将被绘制在与堆栈级别为 0 的定位元素相同的层中,即其父堆叠上下文内。如果透明度小于 1 的元素定位,则“z-index”属性将如[CSS21]中所述应用,但是如果使用的值为“auto”,则该元素的行为与值为“0”时完全相同。有关堆叠上下文的更多信息,请参见[CSS21]第9.9节和附录 E。本段中的规则不适用于 SVG 元素,因为 SVG 有其自己的渲染模型([SVG11]第 3 章)。

我认为它只是说如果你将不透明度设置为除 1 以外的某些值,则该元素将形成自己的堆叠上下文,并且透明元素内的所有内容都将一起变得透明。但在我的示例中,.child 可能会为其内部布局的元素创建自己的堆叠上下文,但该元素本身仍将位于其周围的堆叠上下文中。可以通过将 display: flow-root 设置到 .child 并移除 opacity: 0.5 来强制其创建一个堆叠上下文进行测试,但它将像我通常预期的那样堆叠在 .sibling 后面。

那么这里发生了什么?


1
你的子元素重叠是因为它的高度是150像素,比父元素的高度100像素要高,所以它溢出了父元素。如果你从父元素中移除高度,则父元素将自动获取子元素的高度,子元素就不会重叠了。z-index属性只对定位元素有效,如absolute、relative、fixed、static、sticky等,因此在这里它无效,因为你没有任何定位元素。 - Yogendra Chauhan
2个回答

3
首先,因为没有元素被定位,你应用的z-index是无用的。你的代码可以简化如下:

.element {
  width: 500px;
  height: 100px;
  background: orangered;
}

.child {
  height: 150px;
  width: 100px;
  background: grey;
  
  opacity: 0.5;
}

.sibling {
  width: 400px;
  height: 100px;
  background: skyblue;
}
<div class="element">
  <div class="child"></div>
</div>
<div class="sibling"></div>

然后问题不在于堆叠上下文而是绘制顺序。你关于堆叠上下文的说法是正确的,但在这里是无关紧要的,因为你的.child内没有元素。
从你的引用中可以看出:
如果不透明度小于1的元素未被定位,则它将与具有堆叠级别0的已定位元素一起,在其父堆叠上下文中的同一层上绘制。
然后,如果您检查绘画顺序 所有'z-index:auto'或'z-index:0'的定位后代,按树状顺序排列
从下面我们可以理解,不透明度小于1的元素将像已定位元素一样绘制,并且这些元素将在步骤(8)绘制。 您的其他元素没有特殊之处,也没有创建堆叠上下文,因此它们将在以下内容之前绘制:
对于其流动的、非定位的块级后代,按树状顺序排序:
如果你将透明度替换为position:relative,你将得到相同的结果。

.element {
  width: 500px;
  height: 100px;
  background: orangered;
}

.child {
  height: 150px;
  width: 100px;
  background: grey;
  
  position:relative;
}

.sibling {
  width: 400px;
  height: 100px;
  background: skyblue;
}
<div class="element">
  <div class="child"></div>
</div>
<div class="sibling"></div>

如果你让sibling元素定位,它也会在步骤(8)中被绘制,并且会在.child上方,因为我们遵循树的顺序。

.element {
  width: 500px;
  height: 100px;
  background: orangered;
}

.child {
  height: 150px;
  width: 100px;
  background: grey;
  
  opacity:0.5;
}

.sibling {
  width: 400px;
  height: 100px;
  background: skyblue;
  
  position:relative;
}
<div class="element">
  <div class="child"></div>
</div>
<div class="sibling"></div>


为了总结,当存在子元素时,堆叠上下文的创建才是相关的,因为这将迫使它们在该堆叠上下文内绘制,然后我们考虑绘制顺序以查看每个元素何时被绘制。
更多详细信息的相关问题: 为什么具有 z-index 值的元素无法覆盖其子元素? 为什么 position:relative; 似乎会改变 z-index?

1
虽然您已经得到了答案,但如果您不想减小 .element 的高度,您可以再添加一个CSS属性 overflow: hidden,那么 .child 将不会从 .element 中溢出。

.element {
  width: 500px;
  height: 100px;
  background: orangered;
  overflow: hidden;
}

.child {
  height: 150px;
  width: 100px;
  background: grey;
  
  opacity: 0.5;
  z-index: 1;
}

.sibling {
  width: 400px;
  height: 100px;
  background: skyblue;
  
  z-index: 2;
}
<div class="element">
  <div class="child"></div>
</div>
<div class="sibling"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接