Shai Shprung
Shai Shprung

Reputation: 146

CSS before / after - stacking order. Why both are on top?

I wish that in CSS the before will render before the container, and the after will render after. something like

before : z-index = 0, container: z-index = 1, and after: z-index = 2

but the order is before : z-index = 1, container: z-index = 0, and after: z-index = 2

HTML:

<div id=theDiv>DIV</div>

CSS:

#theDiv{
  position:relative;
  width:100px; height:100px;
  background-color:red;
  margin:50px;
}
#theDiv:before{
  content:"Before";
  position:absolute; top:-30px; left:-30px;
  width:90px; height:90px;
  background-color:blue;
}
#theDiv:after{
  content:"After";
  position:absolute; top:30px; left:30px;
  width:90px; height:90px;
  background-color:yellow;
}

https://jsfiddle.net/shprung/892y1gzc/

My usual solution is to force on the before a z-index of -1 which fill like a hack.

The specs don't mentioned the stacking order by indirectly suggests what I was hoping for :

...As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element's document tree content...

Any better solution than forcing the z-index:-1 ?

Other similar question want to assume that all you need is to setup new stacking content, but this is not the case. for example, if you give each a z-index like the code below it still not behave correctly. so the z-index:-1 for the before is some unique case and this is why I am puzzled.

#theDiv{
  z-index:50;
  position:relative;
  width:100px; height:100px;
  background-color:red;
  margin:50px;
}
#theDiv:before{
  z-index:1;
  content:"Before"; 
  position:absolute; top:-30px; left:-30px;
  width:90px; height:90px;
  background-color:blue;
}
#theDiv:after{
  z-index:100;
  content:"After";
  position:absolute; top:30px; left:30px;
  width:90px; height:90px;
  background-color:yellow;
}

Upvotes: 0

Views: 2885

Answers (1)

Confused One
Confused One

Reputation: 176

::before and ::after create pseudo elements as children of the selected element, not as siblings. So adding a ::before and ::after to #theDiv is similar to creating:

<div id="theDiv">
    <span id="theDiv_before"></span>
    DIV
    <span id="theDiv_after"></span>
</div>

Child elements stack above parent elements, and that's why the pseudo elements display that way.

See this article on the stacking context in CSS for more information.

The solution would be to either create the pseudo elements on the container of your div or else keep using z-index: -1.

Upvotes: 4

Related Questions