Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.Start your free trial
Benjamin Hedgepeth5,672 Points
Child elements within a stacking context
I'm trying to understand the concept of stacking contexts pertaining to child elements. So child elements within a parent container/element, that has its very own stacking context, that happen to be block, inline, or inline-block can have their own stacking context?
I really need someone to illustrate what that would look like? Not sure what I'm mentally visualizing is the same as what I'm interpreting in the MDN resource.
So what does it all mean?
It simply means what context means in normal every day language. The situation, circumstance, or instance, which is unique and separate from others instance, that it's being used.
*Context is the idea of separate 'instances' of something. Two of the same thing (in this case, a z-index) that exist apart from each other. *
Have you ever played something like World of Warcraft or other MMO's? If you have, you know those games often have special group or challenges called dungeons but they're also called "instances". They're called that because while you're still in the overall game, when you enter the 'instance' you're entering a separate mini universe all to itself. It exists within the game, sure, but it has its own things going on in there that are separate from everything else.
That's what's going on with context or scope.
When we learn about z-index, for most, it makes sense. It's just a 3D depth model of how the elements get stacked. Default is 0, the next number is 1, etc..etc.. and elements with higher indexes get stacked on top of others that have lower indexes. We get that. It's rather straightforward even though it can still be a bit confusing at first but usually, once you see it, it clicks.
However, context throws a wrench into the works because things don't work out so cleanly once you start working within context. But once you understand that it's just its own little universe like in the World of Warcraft example, things will start to click.
So, you read the article and you're confused. Let's get rid of that right now with this simple explanation.
Whenever you have an element that has been specifically assigned a positioning property in the CSS(relative, absolute, etc...) that creates a NEW Z-Index that exists solely within that element and is entirely separate from it's parent element or any other ancestor element that happens to have a Z-Index.
That means that the Z-Index within that specific element adheres to its OWN order and has NOTHING to do with the order outside of it. If you take a look at the example on that page, you'll see that all the divs have different Z-Indexes but that some of them don't seem to be stacking properly according to what you learned. Why is a z-index of 6 showing that it's UNDER something within a Z-Index of 5??
Go ahead and take a look at the example they used.
Now take a moment to start to think about "context". Each element that has a position property of some sort has its own context & only siblings obey each others order of the z-index set by its parent.
Stop and repeat that please. Think about it.
Only elements that exists next to each other, inside of a parent with a position property, will follow the same z-index. It makes sense, really. Think about it. Each element that has elements within it is a "parent" of those elements. The parent is what sets the rules for the children.
So take a look at that image there and soak it in.
If the white background is the
body, then that's the parent. What are its children?
Divs #1, #2, and #3.
Notice how they all follow the rules of the z-index.
Div # 1 is index 5 and that's overlapping the pink Div # 3. That makes sense since Div #3 has a z-index of 4.
Div #2 is under div #3. That also makes sense since its index value is 2 and 2 is less than 4
NOW... how in the heck is Div #4, which has an index of 6, displaying UNDER Div #1 which has a z-index of 5??
That's because Div #4 has a brand new context. It exists SOLELY within the universe of Div #3. It exists SOLELY within the context of Div# 3.
Div #3, since it has a position property, has created it's OWN unique z-index that exists within it and div#4 is following the rules of THAT index and that index only so long as it's nested nicely inside of its parent(we'll get to that in a moment)
Honestly, it's just nested indexes, really. Each nested index has to adhere to the current index of its parent and then will have its own index inside of it if it has a position property. What? Well, because its parent has a z-index of 4 within ITS parent element (that body element) Div #4 has to obey that in regard to anything outside of its parent (Div #3)... that's why it's under the Div#1 element which has an index of 5. However, within its own context -- the context of the z-index created by div #3 -- it would totally overlap any of its sibling that had a z-index of 5.
Outside a Context
Remember when how I said a bit earlier "only so long as it's nested nicely inside of its parent". What did I mean by that. Well, with positioning and through the use of margins to shift elements, we can make elements spill outside of their parent element, right?
Ok, so imagine that Div# 5 had a left margin of -30px. that would make it stick out over the left edge of its parent (Div #3) and it would be sticking out into the realm of the body. Well, what do you think would happen? Thiiiink before looking at the next image.
Did you get it right?
So what's going on here?
Same thing I just explained. Div# 5 has a z-index of 1, sure, but ONLY in the context of its parent element, Div#3. As soon as it creeps out into that body region where div# 2 exists, it retains its parent element's index number -- which is 4 -- and thus covers div #2. If it's still confusing, just really take a moment to look at it and think about it.
If a Z-Index represents layers that are stacked from top to bottom, it would make sense that anything that is a child of a particular element that lies along that 'stack' would also occupy the same layer. So if it spills out over that layer, it's still gonna cover whatever was beneath, right?
If you have 3 sheets of paper... red, blue, green (in that order from bottom to top)... and they're kind of fanned out so you can see all the sheets of paper but they're still on top of each other...
Green - top Blue - middle Red - Bottom
and you have 5 other small pieces of paper on the blue paper... and one of them is hanging off the edge a bit, what's it going to do in relation to the red paper? Well, it's gonna cover a portion of it, right? That smaller piece of paper may be overlapped by ALL of the other smaller pieces of paper that exist on top of the blue paper, but no matter what, because the blue paper is above the red paper, if it's hanging over the edge of the blue paper, it's going to overlap the red paper because the layer it exists on (the blue paper) is already over the red paper.
So what is this telling us. It's telling us that
- Each element creates its own context which is simply a different way of saying that it creates its own environment or ecosystem.
- Within that context, a new z-index is created
- Each of its children will follow their own ordering within the parent's context.
- HOWEVER... the children also retain their parent's index value in context of the parent's parent. (in this case, the parent is div #3 and the parent of the parent is the body)
So that's why when Div # 5 -- or rather a portion of Div #5 -- left the context of its parent (Div #3), the portion of it that was sticking out into the body area over Div #2, all of a sudden had to start obeying the rules of THAT context (environment). And it does that by utilizing its parents z-index.
Everything is inherited!! So anything that's a child of a parent that has a z-index also inherits that parent index value in the context of where the parent lies and has its own index value for where it lies itself. I made a small infographic.
So technically, any element that is part of a nested set of indices has its own index value for the context it lies in, but also retains its parents index value in relation to its parent's context. You know, in case it happens to spill out over into its parents context like in my example.
Oooo ... it's ... it's kind of like, ok... so, you're a child and you live with your parents. They have a set of rules of behavior that you must follow in your house. These are the rules, you follow them. The house is the context that your parents created for you the child. That's the context that you exist in (parent > child).
Now, when you go to your grandparents house... they have some different rules and once you're in their house, you follow their rules. Their house is the context that your parents grew up in. They had to follow those rules while in that house(context) and now when you happen to go over granpas house (like when div#5 was spilling out over the edges of its parent container) you now have to follow his rules.
So your grandparents house is like context 1 and your parents house is context 1.1 from the image.
So that's it! Context is merely a unique environment that has its own index set up. It's just "where this thing was created". Was it created within
#content-wrapper? Cool. Then it belongs to the context of the div with the id of content-wrapper. Was it created within
.aside? Cool... its z-index context is the context that exists solely for the div with the class aside that is a child of the div with the id of article-one which is the child of the div with the id of main-content which is a child of the body element.
Anyway, I hope that actually helped and didn't confuse the daylights out of you. If you have any questions, please ask but yo... take some time to mess around. Create a bunch of divs and give them children and start messing with various combos of index values and make the divs overlap and the children overlap each other and then use margin and negative margin to make the children spill outside the borders of their parents into the context above them and see how they interact. You'll get it! And I guarantee this'll be a big help when it comes to scope in JS.
Benjamin Hedgepeth5,672 Points
Your supplemental clarification has clarified things a lot. Not sure I'm 100% on the concept but it helped my comprehension a ton.
Matteo Simeone13,587 Points
Hello Huck, thank you very much for your clear explanation! I was struggling for hours with z-index property in one of my projects and your answer was the one helped me more to understand how it works.
Mark Pryce8,804 Points
Mark Pryce8,804 Points
Nice read on my commute thanks for the effort.