Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I change the z-index stacking order for position: absolute elements?

Here's my code:

body {
    padding: 50px;
}
.rel {
    height: 20px;
    width: 100%;
    background-color: #efefef;
    position: relative;
    margin-bottom: 15px;
}
.abs {
    position: absolute;
    height: 50px;
    width: 300px;
    background-color: red;
    z-index: 1;
}
.abs2 {
    position: absolute;
    top: 0px;
    height: 180px;
    width: 50px;
    background-color: green;
    border: 1px solid black;
    top: -40px;
    z-index: 2;
}
.shift {
    left: 100px;
}
<div class="rel">
    <div class="abs">
        <div class="abs2">1</div>
    </div>
</div>
<div class="rel"></div>
<div class="rel">
    <div class="abs">
        <div class="abs2 shift">2</div>
    </div>
</div>
<div class="rel"></div>
<div class="rel"></div>

Is it possible to stack the green "abs2" div above the second red "abs" div? There are both positioned absolute (every green "abs2" div should be above every red "abs" div).

I know there is something called a stacking context, but I can't figure out how to make my example work. It seems impossible if I read Mozilla's explanation

JSFiddle

like image 533
user63457 Avatar asked Jan 31 '26 15:01

user63457


1 Answers

Since all elements having .abs share the same stacking context, you could give a higher z-index value to that one containing the green block.

Example Here

<div class="rel">
    <div class="abs higher"> <!--
                    ^-- Added class -->
        <div class="abs2"></div>
    </div>
</div>
<div class="rel"></div>
<div class="rel">
    <div class="abs"></div>
</div>
.abs { position: absolute; z-index:1; }

.abs.higher {
    z-index: 2; /* anything bigger than 1 */
}

.abs2 { position: absolute; z-index:1; }

Update

As per your update:

Is it possible to stack the green .abs2 div above the second red .abs div? [...] every green .abs2 div should be above every red .abs div.

Currently both .abs and .abs2 establish new stacking contexts. Assuming the current markup in which .abs2 is nested within .abs, there are two options:

1) The simplest, if it's possible, place .abs2 next to (rather than inside) .abs in the markup, so that they could share the same stacking context: Example.

<div class="rel">
    <div class="abs"></div>
    <div class="abs2">1</div>
</div>
.abs { position: absolute; z-index: 1; }
.abs2 { position: absolute; z-index: 2; }

2) Remove z-index property from .abs to let nested .abs2 position on the top of all elements having .abs class: Example.

However as can be seen, in this approach some parts of .abs elements would go behind the following .rel containers. This is because positioned elements which sit in the same stacking context would stack with the respect to DOM hierarchy unless they have explicit z-index values.

Only in this particular instance 1 - based on the provided demo - we can sort of fix this issue by removing relative positioning of .rel elements. So from now on, .abs elements would be positioned with the respect to the initial containing block (visually, the viewport). This means top/right/bottom/left properties would be calculated relative to the viewport: Example.


1 This is not a general solution. You should use this method with care.

like image 114
Hashem Qolami Avatar answered Feb 03 '26 05:02

Hashem Qolami



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!