Stacking Context behavior

I have the following Sass code:
.image-container#water {
position: relative;
z-index: 1;
background: center / 70% no-repeat url("/water-1.svg") t.$clr-brand-dark;

.drip-drop {
position: absolute;
display: block;
content: "";
top: 1rem;
left: 2rem;
width: 5rem;
height: 5rem;
border-radius: 100%;
background: center / 50% no-repeat url("/drip-drop.svg")
t.$clr-brand-dark;

&::after {
position: absolute;
display: block;
content: "";
bottom: -3px;
right: -3px;
z-index: -1;
width: 100%;
height: 100%;
background-color: t.$clr-brand-muted;
border-radius: 100%;
}
}
}
.image-container#water {
position: relative;
z-index: 1;
background: center / 70% no-repeat url("/water-1.svg") t.$clr-brand-dark;

.drip-drop {
position: absolute;
display: block;
content: "";
top: 1rem;
left: 2rem;
width: 5rem;
height: 5rem;
border-radius: 100%;
background: center / 50% no-repeat url("/drip-drop.svg")
t.$clr-brand-dark;

&::after {
position: absolute;
display: block;
content: "";
bottom: -3px;
right: -3px;
z-index: -1;
width: 100%;
height: 100%;
background-color: t.$clr-brand-muted;
border-radius: 100%;
}
}
}
It produces the first picture. However, what I'm really confused about is when I add z-index: 3 (or some other z-index) to .drip-drop, it produces the second picture, where the ::after psuedo element is above the parent .drip-drop. I don't really know why this behavior exists this way. I have a suspicion it has something to do with stacking context, but I have no idea what stacking context really is and I'm unsure if that's really the issue. Would someone be able confirm if that is the case please?
4 Replies
vince
vinceβ€’12mo ago
So from my reading, it seems that since .drip-drop is a positioned element, it creates a new stacking context, which includes its psuedo element. But then why does specifying the z-index value for .drip-drop bug the whole thing? Oh I think I might understand but I could still be wrong. I'm reading https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context and came across this picture: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context/understanding_zindex_04.png. So from what I understand the z-index value that I would add to .drip-drop would only be evaluated in the stacking context between the parent of .drip-drop and the children of it (.drip-drop). So adding z-index: 3 only effects the z-index positioning within its parent, and not between itself and its psuedo element. Adding z-index: -1 to .drip-drop's psuedo element causes it to go behind .drip-drop, because its stacking context is between itself and .drip-drop. Is this correct? Also follow up question: if I had multiple psuedo elements on .drip-drop that I wanted to layer behind .drip-drop sequentially, would I just give them negative z-index values? It seems that's the case just want to make sure on that. Thanks πŸ™‚
Kevin Powell
Kevin Powellβ€’12mo ago
Sounds like you've got it figured out. Default stacking context is the html element. Everything layers up from that, so adding a z-index will impact it's "level" relative to everything else on the page. If something is positioned, it does not create a new stacking context. If something is positioned and is given a z-index, it creates it's own stacking context. (there are other things that make an element create it's own stacking context too). Once something has created it's own stacking context, anything nested in that element lives in that space now, instead of the entire page, which sounds like you figured out πŸ™‚ As for using negative z-indexs, yeah, you could either give them the same value, and then the first one goes under the second one, or what's easier is just to say -1 and -2, or whatever you want to use πŸ™‚
vince
vinceβ€’12mo ago
Thanks so much πŸ™‚
vince
vinceβ€’12mo ago
Found this really great StackOverflow answer that reinforces this idea as well with a practical example: https://stackoverflow.com/a/20852489/13264587
Stack Overflow
z-index is canceled by setting transform(rotate)
Using transform property, z-index is canceled and appeared in the front. (When commenting out -webkit-transform, z-index is properly working in below code) .test { width: 150px; height: ...