Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

z-index and stacking; removing a child from stacking context

I'm trying to tweak the stacking order of some elements; here's an SSCCE.

Given this HTML snippet:

<div id="block1">
    <div>Lorem ipsum dolor.</div>
    <div id="widget">
        <div>Widgety goodness!</div>
    </div>
</div>
<div id="block2">
    <div>Lorem ipsum dolor.</div>
</div>
<div id="block3">
    <div>Lorem ipsum dolor.</div>
</div>

I'm trying to display #widget on top of #block2; which with the following CSS, you'll see is problematic without changing the location of #widget in the node tree.

#block1, #block2, #block3 {
    position: relative;
    min-height: 50px;
    width: 100%;
}
#block1, #block3 {
    background-color: #abc;
    color: #123;
    z-index: 1;
}
#block2 {
    background-color: #def;
    color: #456;
    z-index: 2;
}
#widget {
    background-color: #f00;
    position: absolute;
    z-index: 999;
    left: 200px;
    top: 40px;
}

As you can see in the fiddle, #widget is overlapped partially by #block2; which makes perfect sense as the parent #block1 is lower among siblings in the stacking order.

The obvious answer is: make #widget a child of #block2, but unfortunately that's not a solution here. Additionally, the #blockN elements cannot have their relative z-index values modified; blocks 1 and 3 must be lower than 2. (by this I mean the calculated values could be different, but #block2 will always be greater than it's siblings). The reason for this, is box-shadow layering.

Is there any reasonable (read: cross-browser, IE7+) way to remove #widget from it's stacking context, while retaining it's position, coordinate location, dimensions, etc.?

Using fixed positioning removes it as desired, however it also obtains all the visual properties of being fixed (which makes it a non-solution)

I reckon this may have been answered in a roundabout way, however I didn't find it. Also, apologies; it appears I may have missed some innocuous but key details in my initial post. I think I've covered them all now.

like image 603
Dan Lugg Avatar asked Aug 19 '13 01:08

Dan Lugg


People also ask

What is a stacking context in HTML?

A stacking context is a group of elements that have a common parent and move up and down the z axis together. In this example, the first parent element has a z-index of 1, so creates a new stacking context. Its child element has a z-index of 999.

What is the z-index of a stacking context?

When applying certain CSS properties, an element can form a stacking context. Z-index values only have a meaning within the same stacking context. For more information on z-index, I recommend this article. I got a lot of inspiration from it when writing this.

How to change the stacking order of elements in CSS?

z-index: In order to change the stacking order, we can use z-index. Element with higher z-index is placed on top of the element with lower z-index. Let us use the same. An important thing to note is that in order to use z-index, elements should be positioned. To learn more about CSS, positions, refer this article.

Why does z-index affect the child elements?

Why is that so? By applying z-index value to an element, a stacking context is formed. The fact that a stacking context is formed means it also affects its child elements (orange box is a child of green box in this case).


2 Answers

Your rules aren't really applying to the elements that you want them to be applied to. You need to explicitly set the z-index on the elements you want to position, in your case that element is the div child of block2. By simply modifying the first selector from:

#block1, #block2 , #block3 {

to

#block1, #block2 div, #block3 {

Your stacking order is corrected. Your z-index rules were being applied to the parents while the children continued to use the default of auto. In your case, by setting the position on #block2 div, you allow your widget to sit on top of the block2 child div.

jsFiddle example

like image 100
j08691 Avatar answered Oct 13 '22 01:10

j08691


I guess you do not need to change the location of the #widget. In my view, the answer lies in your question itself. Check this out

Edited CSS:

#block1{
    background-color: #abc;
    color: #123;
    z-index:3;
}

#block3 {
    background-color: #abc;
    color: #123;
    z-index:1;
}
like image 30
AdityaSaxena Avatar answered Oct 13 '22 03:10

AdityaSaxena