为什么具有 z-index 值的元素不能覆盖其子元素? [英] Why can't an element with a z-index value cover its child?

查看:25
本文介绍了为什么具有 z-index 值的元素不能覆盖其子元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天经过几个小时的调试,我艰难地学会了这条规则:

如果父元素的 z-index 为任何值,则无论您如何更改子元素的 CSS,父元素都永远无法覆盖(堆叠在其顶部)其子元素

我如何从逻辑上理解这种行为?是否符合规范?

.container {宽度:600px;高度:600px;背景颜色:鲑鱼;位置:相对;z-索引:99;填充顶部:10px;}h1{背景颜色:粉红色;位置:相对;z-索引:-1;字体系列:等宽;}

<h1>1.如果我的 z-index 是正数,我就永远不会被父母覆盖.</h1><h1>2.即使我的 z-index 是负数,如果我的父母有任何 z-index,我仍然无法被覆盖.</h1>

解决方案

您需要了解两件重要的事情:绘制顺序和堆叠上下文.如果您参考

我们应该注意,由于transform-styleperspective,使用这种hack可能会产生一些副作用transform 会影响 position:absolute/fixed 元素.相关:父级中断子定位的 CSS 过滤器

Today after hours of debugging, I learned this rule the hard way:

A parent element is never able to cover (stack on top of) its child element if the parent has a z-index of any value, no matter how you change the child's CSS

How can I understand this behavior by logic? Is it in the specs?

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

解决方案

There are two important things you need to know: the painting order and the stacking context. If you refer to the specification, you can find how and when elements are painted.

  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.

It's clear from this that we first paint elements with negative z-index at step (3), then the one with z-index equal to 0 at step (8), and finally the ones with positive z-index at step (9), which is logical. We can also read in another part of 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.

Also

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


To understand when each element will be painted you need to know its stacking context and its stack level inside this stacking context (defined by z-index). You also need to know whether that element establishes a stacking context. This is the tricky part, because setting z-index will do this:

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.


Now we have all the information to better understand each case. If the parent element has a z-index value of something other than auto, then it will create a stacking context, thus the child element will be painted inside whatever their z-index is (negative or positive). The z-index of the child element will simply tell us the order of painting inside the parent element (this covers your second point).

Now, if only the child element has a positive z-index and we set nothing on the parent element, then considering the painting order, the child will be painted later (in step (9)) and the parent in step (8). The only logical way to paint the parent above is to increase the z-index, but doing this will make us fall into the previous case where the parent will establish a stacking context and the child element will belong to it.

There is no way to have the parent above a child element when setting a positive z-index to the child. Also there is no way to have the parent above the child if we set a z-index to the parent element different from auto (either positive or negative).1

The only case where we can have a child below its parent is to set a negative z-index on the child element and keep the parent at z-index: auto, thus this one will not create a stacking context and following the painting order the child will be painted first.


In addition to z-index, there are other properties that create a stacking context. In case you face an expected stacking order, you need to consider those properties, too, in order to see if there is a stacking context created.


Some important facts that we can conclude from the above:

  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: there is some hacky ways if we consider the use of 3D transformation.

Example with an element going under its parent element even if this one has a z-index specified.

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

Another example where we can place an element between two elements in another stacking context:

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

We can also have some crazy stacking order like below:

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

We should note that using such hack may have some side effect due to the fact that transform-style, perspective and transform will affect position:absolute/fixed element. Related: CSS-Filter on parent breaks child positioning

这篇关于为什么具有 z-index 值的元素不能覆盖其子元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆