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>
      

Run codeHide result


Can the green "abs2" div be stacked above the second red "abs" div? Both positional absolutes (every green "abs2" div must be above every red "abs" div).

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

JSFiddle

+3


source to share


2 answers


Since all the elements that have .abs

have the same stacking context, you can give a higher value z-index

to the one that contains the green box.

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 must be above every red .abs

div.

Currently both .abs

and .abs2

set a new stacking contexts. Assuming the current markup is .abs2

nested in .abs

, there are two options:



1) Simplest, if possible, put .abs2

next to (and not inside) .abs

in markup so they can 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 property z-index

from .abs

to insert nested position .abs2

at the top of all elements that have a class .abs

: Example .

However, as you can see, in this approach, some parts of the elements .abs

will lag behind the following containers .rel

. This is because positioned elements that are in the same stacking context will stack based on the DOM hierarchy unless they have explicit values z-index

.

Only in this particular instance 1 - based on the demo provided - we can fix this issue by removing the relative

positioning of the elements .rel

. So now the elements .abs

will be positioned relative to the initial containing block (visually, viewport). This means that the properties top

/ right

/ bottom

/ left

will be calculated relative to the viewport: Example .


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

+3


source


You also need to specify a higher z-index for the parent container. You already have position: relative

on rel

, which is also needed, so adding a z-index should do that.



+1


source







All Articles