css - 为什么具有 z-index 值的元素不能覆盖其子元素?

标签 css css-position z-index

今天经过几个小时的调试,我很难学会这条规则:
如果父元素的 z-index 为任意值,则无论您如何更改子元素的 CSS ,父元素都永远无法覆盖(堆叠在其上)其子元素
我怎样才能从逻辑上理解这种行为?它在规范中吗?

.container {
  width: 600px;
  height: 600px;
  background-color: salmon;
  position: relative;
  z-index: 99;
  padding-top: 10px;
}

h1 {
  background-color: pink;
  position: relative;
  z-index: -1;
  font-family: monospace;
}
<div class="container">
  <h1>1. I can never be covered by parent if my z-index is positive.</h1>
  <h1>2. Even when my z-index is nagative, I still can never be covered if my parent has any z-index at all.</h1>
</div>

Negative z-index child above parent element

最佳答案

您需要了解两件重要的事情:绘画顺序和堆叠上下文。如果您引用the specification ,您可以找到绘制元素的方式和时间。

  1. Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.


  1. All positioned, opacity or transform descendants, in tree order that fall into the following categories:
    1. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.


  1. Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.


从这里可以清楚地看出,我们首先用负值 z-index 绘制元素。在步骤 (3),然后是 z-index在第 (8) 步等于 0,最后是正值 z-index在步骤(9),这是合乎逻辑的。我们还可以阅读 the specification 的另一部分:

Each box belongs to one stacking context. Each box in a given stacking context has an integer stack level, which is its position on the z-axis relative to other boxes in the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked bottom-to-top according to document tree order.





An element that establishes a local stacking context generates a box that has two stack levels: one for the stacking context it creates (always 0) and one for the stacking context to which it belongs (given by the z-index property).



要了解何时绘制每个元素,您需要知道 它的堆叠上下文 它的堆栈级别在此堆叠上下文中(由 z-index 定义)。您还需要知道该元素是否建立了堆叠上下文。这是棘手的部分,因为设置 z-index会这样做:

For a positioned box, the z-index property specifies:

  1. The stack level of the box in the current stacking context.
  2. Whether the box establishes a stacking context

Values have the following meanings:

<integer>

This integer is the stack level of the generated box in the current stacking context. The box also establishes a new stacking context.

auto

The stack level of the generated box in the current stacking context is 0. The box does not establish a new stacking context unless it is the root element.



现在我们拥有所有信息,可以更好地了解每个案例。如果父元素有 z-index auto 以外的值,然后它将创建一个堆叠上下文,因此子元素将被绘制在它们的z-index中。是(负或正)。 z-index的子元素将简单地告诉我们父元素内的绘画顺序(这涵盖了您的第二点)。

现在,如果只有子元素具有正值 z-index并且我们在父元素上没有设置任何内容,然后考虑绘制顺序,子元素将稍后绘制(在步骤(9)中),父元素将在步骤(8)中绘制。绘制上面父级的唯一合乎逻辑的方法是增加 z-index ,但是这样做会让我们陷入之前的情况,即父元素会建立一个堆叠上下文,子元素会属于它。

没办法在设置 时让父元素在子元素之上正 z-index给 child 。还有没办法如果我们设置 z-index,则让父级高于子级到不同于 auto 的父元素(正面或负面).1

我们可以在其父级之下有一个子级的唯一情况是设置一个负数 z-index在子元素上并将父元素保持在 z-index: auto ,因此这个不会创建堆叠上下文,并且按照绘画顺序, child 将首先被绘画。

除了z-index ,有other properties that create a stacking context .如果您遇到预期的堆叠顺序,您还需要考虑这些属性,以便查看是否创建了堆叠上下文。

我们可以从上面得出一些重要的事实:

  1. Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
  2. Each stacking context is completely independent of its siblings: only descendant elements are considered when stacking is processed.
  3. Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context. ref


1:如果我们考虑使用 3D 变换,有一些 hacky 方法。

一个元素位于其父元素之下的示例,即使该元素具有 z-index指定的。

.box {
  position:relative;
  z-index:0;
  height:80px;
  background:blue;
  transform-style: preserve-3d; /* This is important */
}
.box > div {
  margin:0 50px;
  height:100px;
  background:red; 
  z-index:-1; /* this will do nothing */
  transform:translateZ(-1px); /* this will do the magic */
}
<div class="box">
  <div></div>
</div>


另一个例子,我们可以在另一个堆叠上下文中的两个元素之间放置一个元素:

.box {
  position: relative;
  z-index: 0;
  height: 80px;
  background: blue;
}

.box>div {
  margin: 0 50px;
  height: 100px;
  background: red;
  z-index: 5;
  transform: translateZ(2px);
}

.outside {
  height: 50px;
  background: green;
  margin: -10px 40px;
  transform: translateZ(1px);
}

body {
  transform-style: preserve-3d;
}
<div class="box">
  <div></div>
</div>

<div class="outside"></div>


我们也可以有一些疯狂的堆叠顺序,如下所示:

.box {
  width: 100px;
  height: 100px;
  position: absolute;
}

body {
  transform-style: preserve-3d;
}
<div class="box" style="top:100px;left:50px;background:red;"></div>
<div class="box" style="top: 50px;left: 115px;background:blue;"></div>
<div class="box" style="top: 101px;left: 170px;background:green;"></div>
<div class="box" style="top: 175px;left: 115px;background:purple;transform: rotateY(-1deg);"></div>


CSS circular stacking context

我们应该注意到,由于 transform-style 的事实,使用这种 hack 可能会产生一些副作用。 , perspectivetransform会影响position:absolute/fixed元素。相关:CSS-Filter on parent breaks child positioning

关于css - 为什么具有 z-index 值的元素不能覆盖其子元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57173659/

相关文章:

javascript - 在属性 unicode 无法正常工作之前引导

css - 使导航栏中的 div 在响应式菜单中显示

html - 如何避免一个 DIV 溢出另一个?

css - 固定元素上的径向框阴影

silverlight - 我们如何以编程方式更改 Silverlight 控件的 z 索引?

css - 如何列出一系列包含相同属性的类并为每个类分配不同的 z-index

php - 使用 CSS 格式化 PHP 问题

jquery - 从 slect2.js 标签中的选项获取类

具有自动高度的相对位置 div 上的 CSS 间距底部

html - z-index 不能正常工作