Search code examples
cssz-indexpseudo-element

How can I put pseudo element behind parent?


I looked for solutions and tried all the suggestions from this SO, but I failed all of that.
I wanna make a border as peseudo element behind parent.

.member__profile-container {
  flex-basis: 50rem;
  position: relative;
  z-index: 4;
}

.member__profile {
  padding-top: 150%;
  background-image: url('../images/irene.jpg');
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  box-shadow: 0 -1rem .5rem 1rem rgba(0,0,0,0.3);
  margin-right: 4rem;
  transform: rotate(-5deg) translateX(-10%);
  animation: expand 1s ease .5s forwards;
}

.member__profile:before {
  content: ' ';
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  border: 10px solid white;
  transform: rotate(-5deg) translateX(-10%);
  animation: expand 1s ease .5s forwards;
}
<div class="member__profile-container">
  <div class="member__profile"></div>
</div>

Result is like below, but border must be behind parent.

NOT WORKING EXAMPLE


Solution

  • To make it work I had to modify your html a bit.
    Because of the transformation in .member__profile a stacking context is created at this level and since the ::before element is a descendant of his element, z-index will only move the pseudo element inside .member__profile.

    HTML

     <div class="member__profile-container">
         <div class="member__profile"></div>
    
         <!-- moved the pseudo-element to a sibling element -->
         <!-- removing 'the transform' inside .member__profile and 
              keeping the pseudo element would also work -->
    
         <div class="member__undercover"></div>
     </div>
    

    CSS

    .member__profile-container {
      /* creating a stacking context on the parent */
      position: relative;
      z-index: 1;
      flex-basis: 50rem;
      /* added color to make position clearer */
      background-color: green;
    }
    
    
    .member__profile {
      position: relative;
      padding-top: 150%;
      background-image: url('../images/irene.jpg');
      /* added color to make position clearer */
      background-color: red;
      background-repeat: no-repeat;
      background-position: center;
      background-size: cover;
      box-shadow: 0 -1rem .5rem 1rem rgba(0, 0, 0, 0.3);
      margin-right: 4rem;
      transform: rotate(-5deg) translateX(-10%);
      z-index: 0;
    }
    
    .member__undercover {
      position: absolute;
      left: 0;
      top: 0;
      height: 100%;
      width: 100%;
      border: 10px solid white;
      transform: rotate(-5deg) translateX(-10%);
      /* added color to make position clearer */
      background-color: blue;
      z-index:-1;
    }
    

    By using "position: relative; z-index: 1;" on the container I create a stacking context on this level and can reorder freely it's children with z-index.
    If you use z-index without creating a stacking context in the container then you will be using a stacking context somewhere else where one has been created in your document, or ultimately the body if none exist before.
    If you want the border behind the container not the profile, you just need to move "position: relative; z-index: 1;" up one parent (not copy it, move it).

    To understand more about the stacking context : MDN, The stacking context