Reputation: 1162
I am having trouble properly stacking my divs using CSS z-index
. In my code, if I set .nose::before
and .nose::after
to z-index: -1
, it puts the two divs at the very back of the stack. However, I just these divs to sit behind the .nose
div. Here's my code:
*, *::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>
Upvotes: 3
Views: 483
Reputation: 2671
In short: Set z-index on your head element. Move ears out of the head element.
Here is why.
z-index
has stacking contexts. Each of those contexts has a root element (just any html element). Now, to become a root element it must comply with any of the following rules:
<html>
elementstatic
and z-index other than auto
So the default stacking context is with the <html>
element as a root.
Once the element is inside a scope (in other words, child of a root element), it can only be positioned relative to the elements inside the scope.
Think about it as a nested list.
Wrap here is a root element, as it has position set to relative and z-index to 1. And all of its children are now inside a stacking scope with the Wrap as a root.
So, like in a nested list, children of a particular element cannot appear before its root. For example, Child2
cannot appear before the Wrap
, since it is scoped inside of it. But it can appear before the Child1
.
Now, in your case the structure is as follows:
Notice that the head is not a root, because it doesn't comply with the rules for becoming one (positioned elements must also have z-index other than auto). Therefore when you assign z-index of -1
to the Nose::before and ::after you get this:
The elements have been positioned all the way behind the Head, because they are in the same stacking scope. But they appear on top of Head::before
, since when elements have the same z-index, they are stacked according to the order of appearance in html.
Now, to prevent head children from appearing behind it, you must add z-index to it. This will make it a root element of new stacking scope.
But this creates another problem. Now ears are positioned on top of the head. This is not possible to solve with css alone, since they are inside a stacking scope of the head. And root always lies behind every of its children.
To solve it, you must move the ears out of the head. So, it means, you won't be able to use pseudoelements (before & after) anymore. I suggest creating ear elements outside of the head and wrapping everything in some other element (named bear?) with position relative. Wrapper is needed if you still want to position ears relative to the head.
The answer is mostly inspired by this article.
Upvotes: 1