使用 z-index 堆叠伪元素
stacking pseudo-elements with z-index
我在使用 CSS z-index
正确堆叠 div 时遇到问题。在我的代码中,如果我将 .nose::before
和 .nose::after
设置为 z-index: -1
,它会将两个 div 放在堆栈的最后面。但是,我只是把这些divs 坐到了.nose
后面div。这是我的代码:
*, *::after, *::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body { height: 100%; }
body {
background: #44BBA4;
}
.head {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 375px;
width: 400px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
}
.head::before, .head::after {
content: "";
position: absolute;
height: 90px;
width: 90px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
.head::before {
top: -30px;
left: 40px;
}
.head::after {
top: -30px;
right: 40px;
}
.eye {
position: absolute;
top: 150px;
height: 25px;
width: 25px;
background: #000;
border-radius: 50%;
}
.eye.left {
left: 90px;
}
.eye.right {
right: 90px;
}
.eye::before {
content: "";
position: absolute;
top: -50px;
left: -37px;
height: 100px;
width: 100px;
border-radius: 50%;
border: 12px solid transparent;
border-top: 12px solid #000;
}
.nose {
position: absolute;
margin: auto;
right: 0;
left: 0;
bottom: 130px;
height: 30px;
width: 30px;
background: #000;
border-radius: 50%;
}
.nose::before, .nose::after {
content: "";
position: absolute;
height: 68px;
width: 73px;
background: #fff;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
<div class="head">
<div class="eye left"></div>
<div class="eye right"></div>
<div class="nose"></div>
</div>
简而言之: 在你的 head 元素上设置 z-index。将耳朵移出头部元素。
原因如下。
z-index
有堆叠上下文。这些上下文中的每一个都有一个根元素(只是任何 html 元素)。现在,要成为根元素,它必须符合以下任一规则:
- 成为
<html>
元素
- 除
static
以外的位置和auto
以外的z-index
- 不透明度小于 1
所以默认的堆叠上下文是以 <html>
元素为根。
一旦元素在范围内(换句话说,根元素的 child),它只能相对于范围内的元素定位。
将其视为嵌套列表。
这里的 Wrap 是一个根元素,因为它的位置设置为 relative 并且 z-index 设置为 1。它的所有 children 现在都在一个以 Wrap 为根的堆叠范围内.
因此,就像在嵌套列表中一样,特定元素的 children 不能出现在其根之前。例如,Child2
不能出现在 Wrap
之前,因为它在其中。但它可以出现在 Child1
.
之前
现在,在您的情况下,结构如下:
注意 head 不是根,因为它不符合成为一个的规则(定位元素也必须有 z-index 除了 auto)。因此,当您将 -1
的 z-index 分配给 Nose::before 和 ::after you get this:
元素一直位于 Head 后面,因为它们在相同的堆叠范围内。但是它们出现在Head::before
之上,因为当元素具有相同的z-index时,它们是按照在html.
中出现的顺序堆叠的
现在,为了防止头children出现在它后面,你必须给它加上z-index。这将使它成为新堆叠范围的根元素。
但这又产生了另一个问题。现在耳朵位于头顶。这不可能单独使用 css 来解决,因为它们在头部的堆叠范围内。并且 root 始终位于其每个 children.
之后
要解决这个问题,你必须把耳朵从头上移开。因此,这意味着您将无法再使用伪元素(之前和之后)。我建议在头部外部创建耳朵元素,并将所有内容包裹在其他元素(名为熊?)中,并具有相对位置。如果您仍想相对于头部定位耳朵,则需要包装器。
答案主要受 this article 启发。
我在使用 CSS z-index
正确堆叠 div 时遇到问题。在我的代码中,如果我将 .nose::before
和 .nose::after
设置为 z-index: -1
,它会将两个 div 放在堆栈的最后面。但是,我只是把这些divs 坐到了.nose
后面div。这是我的代码:
*, *::after, *::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body { height: 100%; }
body {
background: #44BBA4;
}
.head {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 375px;
width: 400px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
}
.head::before, .head::after {
content: "";
position: absolute;
height: 90px;
width: 90px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
.head::before {
top: -30px;
left: 40px;
}
.head::after {
top: -30px;
right: 40px;
}
.eye {
position: absolute;
top: 150px;
height: 25px;
width: 25px;
background: #000;
border-radius: 50%;
}
.eye.left {
left: 90px;
}
.eye.right {
right: 90px;
}
.eye::before {
content: "";
position: absolute;
top: -50px;
left: -37px;
height: 100px;
width: 100px;
border-radius: 50%;
border: 12px solid transparent;
border-top: 12px solid #000;
}
.nose {
position: absolute;
margin: auto;
right: 0;
left: 0;
bottom: 130px;
height: 30px;
width: 30px;
background: #000;
border-radius: 50%;
}
.nose::before, .nose::after {
content: "";
position: absolute;
height: 68px;
width: 73px;
background: #fff;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
<div class="head">
<div class="eye left"></div>
<div class="eye right"></div>
<div class="nose"></div>
</div>
简而言之: 在你的 head 元素上设置 z-index。将耳朵移出头部元素。
原因如下。
z-index
有堆叠上下文。这些上下文中的每一个都有一个根元素(只是任何 html 元素)。现在,要成为根元素,它必须符合以下任一规则:
- 成为
<html>
元素 - 除
static
以外的位置和auto
以外的z-index - 不透明度小于 1
所以默认的堆叠上下文是以 <html>
元素为根。
一旦元素在范围内(换句话说,根元素的 child),它只能相对于范围内的元素定位。
将其视为嵌套列表。
这里的 Wrap 是一个根元素,因为它的位置设置为 relative 并且 z-index 设置为 1。它的所有 children 现在都在一个以 Wrap 为根的堆叠范围内.
因此,就像在嵌套列表中一样,特定元素的 children 不能出现在其根之前。例如,Child2
不能出现在 Wrap
之前,因为它在其中。但它可以出现在 Child1
.
现在,在您的情况下,结构如下:
注意 head 不是根,因为它不符合成为一个的规则(定位元素也必须有 z-index 除了 auto)。因此,当您将 -1
的 z-index 分配给 Nose::before 和 ::after you get this:
元素一直位于 Head 后面,因为它们在相同的堆叠范围内。但是它们出现在Head::before
之上,因为当元素具有相同的z-index时,它们是按照在html.
现在,为了防止头children出现在它后面,你必须给它加上z-index。这将使它成为新堆叠范围的根元素。
但这又产生了另一个问题。现在耳朵位于头顶。这不可能单独使用 css 来解决,因为它们在头部的堆叠范围内。并且 root 始终位于其每个 children.
之后要解决这个问题,你必须把耳朵从头上移开。因此,这意味着您将无法再使用伪元素(之前和之后)。我建议在头部外部创建耳朵元素,并将所有内容包裹在其他元素(名为熊?)中,并具有相对位置。如果您仍想相对于头部定位耳朵,则需要包装器。
答案主要受 this article 启发。