48

I need a certain dynamic element to always appear on top of another element, no matter what order in the DOM tree they are. Is this possible? I've tried z-index (with position: relative), and it doesn't seem to work.

I need:

    <div class="a">
        <div class="b"></div>
    </div>

    <div class="b">
        <div class="a"></div>
    </div>

To display exactly the same when rendered. And for flexibility purposes (I'm planning on distributing a plugin that needs this functionality), I'd really like to not have to resort to absolute or fixed positioning.

For what it's worth, to perform the function I was wanting, I made a conditional statement where the overlapping child element would become transparent in the case it was blocking the view of its parent. It's not perfect, but it's something.

Nexo
  • 2,125
  • 2
  • 10
  • 20
dclowd9901
  • 6,756
  • 9
  • 44
  • 63
  • 1
    This _is_ possible - assuming you only have nesting of 1 level deep (as in the example). This will work: `.a > .b, .b > .a {z-index: -1; position: relative}`. If you need a fiddle, comment, but I think it's pretty self explanatory. – Ivan Durst Jun 17 '15 at 22:13

7 Answers7

51

You can do this in modern browsers now using transform 3D with CSS. It wasn't really possible in 2010 but it is now.

.parent {
  background: red;
  width: 100px;
  height: 100px;
  transform-style: preserve-3d;
  position: relative;
}

.child {
  background: blue;
  width: 100px;
  height: 100px;
  position: absolute;
  top: -5px;
  left: -5px;
  transform: translateZ(-10px)
}
<div class="parent">
  Parent
  <div class="child">
    Child
  </div>
</div>
zyrup
  • 691
  • 2
  • 10
  • 18
Johnny
  • 9,725
  • 5
  • 29
  • 34
31

If the elements make a hierarchy, it cannot be done that way, because every positioned element creates new stacking context, and z-index is relative to the elements of the same stacking context.

jholster
  • 5,066
  • 1
  • 27
  • 20
  • 2
    I pretty much thought this was the case, but I don't presume to know everything. Either way, thanks all. – dclowd9901 Mar 23 '10 at 21:58
  • although this is the accepted answer, (maybe this answer was correct at the time? but) this is not true -- see other answers for ways to get child behind parent. (I just did it accidentally, where I had previously assumed it was impossible, and found this question while searching to find how it happened) – Kevin Wang May 18 '20 at 08:48
  • If you set the z-index of the child to -1, then it goes behind it's parent element – Tiernan Crotty Jul 27 '21 at 08:02
5

I figured out a way to actually put the child element behind its element by creating a pseudo-element which mimics the parent. Useful for stuff like dropdown-menus - hope it helps, user from eight years ago!

div {
  position: relative;
}
 .container > div {
  float: left;
  background-color: red;
  width: 150px;
  height: 50px;
  z-index: 10;
}
 .container > div:before {
  content: '';
  display: block;
  position: absolute;
  height: 100%;
  width: 100%;
  background-color: red;
  z-index: 7;
  top: 10px;
}
 .a > .b, .b > .a {
  z-index: 5;
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: teal;
}
 .a + .b {
  margin-left: 20px;
}
 
<div class="container">
  <div class="a">
    <div class="b"></div>
  </div>

  <div class="b">
    <div class="a"></div>
  </div>
</div>
moeses
  • 497
  • 1
  • 6
  • 21
2

The answer for the question

How to get a child element to show behind (lower z-index) than its parent?

is to:

  • Make the parent not a stacking context
  • Make the child a positioned stacking context, whose z-index smaller than 0.

Notice: I said make the child a positioned stacking context, not just stacking context, because pay attention that z-index will only be valid for positioned element)

About how an element is considered a stacking context, read this, and how an element is considered a positioned element, read this. Or a great explanation from this answer.


Conclusion:

  • Make sure the parent is not a stacking context
  • Make sure the child is a stacking context
  • Make sure the child's z-index is smaller than 0
  • Make sure the child is a positioned element so that the z-index from last step is applicable

Yet you have to understand 2 terms stacking context and positioned element

Loi Nguyen Huynh
  • 8,492
  • 2
  • 29
  • 52
1

I've had success using the following.

z-index: -1;

Damir Kotoric
  • 901
  • 6
  • 8
  • 7
    This does not answer the question being asked – Zach Saucier Sep 14 '14 at 21:26
  • 5
    Upvoted, this does not deserve a downvote. This _partially_ answers the question being asked - it would be better if he demonstrated with a fiddle. – Ivan Durst Jun 17 '15 at 22:10
  • 3
    This does deserve a downvote because it is incorrect. The question specifies getting a child element to display behind its parent using z-index and without using absolute positioning. As jholster has explained it cannot be achieved this with these conditions. – Luke May 06 '18 at 11:47
  • 1
    For fixed positioning of both child and parent element it works. Upvoted. – Lis Oct 04 '19 at 18:41
1
.element--child{
  position:relative;
  z-index:-1;
}
Abhishek
  • 546
  • 5
  • 13
0

what you need is position: absolute in order for z-index to work.

also you will need to set the left and top css properties to position the element in the correct place. You will probably need to do this with javascript.

mkoryak
  • 57,086
  • 61
  • 201
  • 257