Is it possible to set the stacking order of pseudo

2019-01-01 08:27发布

问题:

I am trying to style a element with the :after pseudo element CSS selector

#element {
    position: relative;
    z-index: 1;
}

#element::after {
    position:relative;
    z-index: 0;
    content: \" \";
    position: absolute;
    width: 100px;
    height: 100px;
}

It seems like the ::after element can not be lower then the element itself.

Is there a way to have the pseudo element lower then the element itself?

回答1:

Pseudo-elements are treated as descendants of their associated element. To position a pseudo-element below its parent, you have to create a new stacking context to change the default stacking order.
Positioning the pseudo-element (absolute) and assigning a z-index value other than “auto” creates the new stacking context.

#element { 
    position: relative;  /* optional */
    width: 100px;
    height: 100px;
    background-color: blue;
}

#element::after {
    content: \"\";
    width: 150px;
    height: 150px;
    background-color: red;

    /* create a new stacking context */
    position: absolute;
    z-index: -1;  /* to be below the parent element */
}
<!DOCTYPE html>
<html>
<head>
  <meta charset=\"utf-8\">
  <title>Position a pseudo-element below its parent</title>
</head>
<body>
  <div id=\"element\">
  </div>
</body>
</html>



回答2:

I know this is an old thread, but I feel the need to post the proper answer. The actual answer to this question is that you need to create a new stacking context on the parent of the element with the pseudo element (and you actually have to give it a z-index, not just a position).

Like this:

#parent {
    position: relative;
    z-index: 1;
}
#pseudo-parent {
    position: absolute;
    /* no z-index allowed */
}
#pseudo-parent:after {
    position: absolute;
    top:0;
    z-index: -1;
}

It has nothing to do with using :before or :after pseudo elements.

#parent { position: relative; z-index: 1; }
#pseudo-parent { position: absolute; } /* no z-index required */
#pseudo-parent:after { position: absolute; z-index: -1; }

/* Example styling to illustrate */
#pseudo-parent { background: #d1d1d1; }
#pseudo-parent:after { margin-left: -3px; content: \"M\" }
<div id=\"parent\">
 <div id=\"pseudo-parent\">
   &nbsp;
 </div>
</div>



回答3:

There are two issues are at play here:

  1. The CSS 2.1 specification states that \"The :before and :after pseudo-elements elements interact with other boxes, such as run-in boxes, as if they were real elements inserted just inside their associated element.\" Given the way z-indexes are implemented in most browsers, it\'s pretty difficult (read, I don\'t know of a way) to move content lower than the z-index of their parent element in the DOM that works in all browsers.

  2. Number 1 above does not necessarily mean it\'s impossible, but the second impediment to it is actually worse: Ultimately it\'s a matter of browser support. Firefox didn\'t support positioning of generated content at all until FF3.6. Who knows about browsers like IE. So even if you can find a hack to make it work in one browser, it\'s very likely it will only work in that browser.

The only thing I can think of that\'s going to work across browsers is to use javascript to insert the element rather than CSS. I know that\'s not a great solution, but the :before and :after pseudo-selectors just really don\'t look like they\'re gonna cut it here.



回答4:

Speaking with regard to the spec (http://www.w3.org/TR/CSS2/zindex.html), since a.someSelector is positioned it creates a new stacking context that its children can\'t break out of. Leave a.someSelector unpositioned and then child a.someSelector:after may be positioned in the same context as a.someSelector.



回答5:

Try it out

el {
  transform-style: preserve-3d;
}
el:after {
  transform: translateZ(-1px);
}


回答6:

I know this question is ancient and has an accepted answer, but I found a better solution to the problem. I am posting it here so I don\'t create a duplicate question, and the solution is still available to others.

Switch the order of the elements. Use the :before pseudo-element for the content that should be underneath, and adjust margins to compensate. The margin cleanup can be messy, but the desired z-index will be preserved.

I\'ve tested this with IE8 and FF3.6 successfully.



回答7:

Set the z-index of the :before or :after pseudo element to -1 and give it a position that honors the z-index property (absolute, relative, or fixed). This works because the pseudo element\'s z-index is relative to its parent element, rather than <html>, which is the default for other elements. Which makes sense because they are child elements of <html>.

The problem I was having (that lead me to this question and the accepted answer above) was that I was trying to use a :after pseudo element to get fancy with a background to an element with z-index of 15, and even when set with a z-index of 14, it was still being rendered on top of its parent. This is because, in that stacking context, it\'s parent has a z-index of 0.

Hopefully that helps clarify a little what\'s going on.