cssstacking-context

CSS: Penrose stairs stacking effect


I want to do an effect similar to a Penrose stair where you have element-1 on top of element-2 but behind element-3 witch is behind of element-2 a bit complicated from what I can tell.

I have this code

<body>
  <div class="parent">
    <div id="s1" class="square"><div></div></div>
    <div id="s2" class="square"><div></div></div>
  </div>
</body>
.parent {
  width: 300px;
  height: 300px;
  border-radius: 25px;
  background: orange;
  position: relative;
}
.square{
  display: inline-block;
  position: absolute;
  z-index: 10;
}
#s1{
  --Color: teal;
  left: calc(100px);
  top: calc(100px);
  transform: rotate(45deg);
}
#s2{
  --Color: cornflowerblue;
  right: calc(100px);
  bottom: calc(100px);
  transform: rotate(-135deg);
}
.square>div{
  width: 50px;
  height: 50px;
  border-radius: 10px;
  background: var(--Color);
  opacity: 1;
}
.square>div:before{
  content: " ";
  display: inline-block;
  position: relative;
  width: 100px;
  height: 8px;
  background: var(--Color);
  background: #000;
  z-index: -1;
  top: 5px;
  left: 5px;
}

The code has two elements both with a before reaching the other element, this is a simplified version of my problem, but I want to have the before behind both elements.

There are some other restrictions I need to consider, this should be responsive so I can't get away with a set width so easely. Also, I'm trying to keep it as vanilla as possible.

Edit 1:

I'm want to acheave this effect


Solution

  • You can make each box elements full width in two elements. One side having a higher z-index than the other side and the thin lines. This will give the illusion that you hove one box instead of pseudo elements to make up the entirety of your box element. Adjust the radius of each combining element so it is only on the two corners it needs to be. Adjust the positioning of each absolute element to line up with its corresponding colored half.

    -- EDIT: OP asked to have the two black lines below the two box elements --

    In this case you can use the #s2 pseudo element copying the properties to recreate the same box, make it position: absolute then move it left using positioning essentially covering up the two black lines.

    Because the second element is parsed after the first in the DOM and they are sort of tied at the hip; one set being a box and its child element the black line, we use the second parent elements pseudo element #s2:after to cover the first as it will naturally sit on top of both elements in z-indices.

    -- end of edit --

    NOTE: I also created divs out of your span elements as a div is a block level element and should not be nested inside SPAN.

    My example is just down and dirty but it should illustrate how this illusion can be achieved.

    .parent {
      width: 300px;
      height: 300px;
      border-radius: 25px;
      background: orange;
      position: relative;
    }
    .square{
      display: inline-block;
      position: absolute;
      z-index: 10;
    }
    #s1{
      --Color: teal;
      left: calc(100px);
      top: calc(100px);
      transform: rotate(45deg);
      position: relative;
      z-index: 1;
    }
    #s2{
      --Color: cornflowerblue;
      right: calc(100px);
      bottom: calc(100px);
      transform: rotate(-135deg);
    }
    #s2:after{
      content: "";
      position: absolute;
      background-color: teal;
      border-radius: 10px;
      top: 0;
      left: 70px;
      width: 100%;
      height: 100%;
    }
    .square>div{
      width: 50px;
      height: 50px;
      border-radius: 10px;
      background: var(--Color);
      opacity: 1;
    }
    .square>div:before{
      content: " ";
      display: inline-block;
      position: relative;
      width: 100px;
      height: 8px;
      background: #000;
      z-index: -1;
      top: 5px;
      left: 5px;
    }
    <body>
      <div class="parent">
        <div id="s1" class="square"><div></div></div>
        <div id="s2" class="square"><div></div></div>
      </div>
    </body>