Search code examples
htmlcssz-indexmargin

z-index and stacking order - make child lower than parent but higher than uncle


Please see the code in jsbin

Screenshot:

enter image description here

All I need is just to have blue on top, then white, then greens. So ideally:

enter image description here

I tried z-index, create stacking context... nothing worked.

It might have something to do with negative margin in CSS

I'm happy to change the HTML code or change the current CSS, as long as I can get the desired effect.

.left,
.right {
  width: 200px;
  height: 60px;
  background-color: green;
  display: inline-block;
}
.bar {
  width: 20px;
  height: 60px;
  background-color: blue;
  display: inline-block;
}
.circle {
  height: 40px;
  width: 40px;
  background-color: white;
  border-radius: 50%;
  margin-left: -10px;
  margin-top: 10px;
}
<div class="out">
  <div class="left"></div>
  <div class="bar">
    <div class="circle"></div>
  </div>
  <div class="right"></div>
</div>

Edit

I should have mentioned that my difficulty was mostly achieving the effect while keeping the current HTML setup (i.e. circle in bar). Turns out it doesn't seem possible, because

  1. If no zindex on bar, can't make sure it's on top of circle
  2. If set zindex on bar, then it creates new stacking context, then circle can't be on top of 2 greens. Because greens are on different stacking context

Solution

  • EDITED : edited my answer after reading more carefully :) sorry about that

    see here > jsFiddle

    or snippet below :

    .left, .right {
      width: 200px;
      height: 60px;
      background-color: green;
      display: inline-block;
        position:relative;
           z-index:1;
    }
    
    .bar {
      width: 20px;
      height: 60px;
      background-color: blue;
      display: inline-block;
      z-index:6;
      position:relative;
     
    
    }
    .circle {
      height: 40px;
      width: 40px;
      background-color: white;
      border-radius: 50%;
      top: 10px;
      position:absolute;
     
     left:0;
     right:0;
      margin:0 auto;
      z-index:5;
    }
    .out {width:420px;position:relative;}
    <div class="out">
        <div class="left"></div><div class="bar"></div><div class="circle"></div><div class="right"></div>
    </div>

    OR if you don't want different bg color for .left and .right just use one big div .out and position the bar and circle on top of it :

    .out {
      position: relative;
      width: 420px;
      height: 60px;
      background-color: green;
    }
    .bar {
      width: 20px;
      height: 100%;
      background-color: blue;
       position: absolute;
      left: 0;
      right:0;
      margin:0 auto;
      z-index: 2
    }
    .circle {
       height: 40px;
      width: 40px;
      background-color: white;
      border-radius: 50%;
       position: absolute;
      top: 10px;
       left: 0;
      right:0;
      margin:0 auto;
      z-index: 1
    }
    <div class="out">
        <div class="bar"></div>
        <div class="circle"></div>
    </div>