Is it possible to set the stacking order of pseudo-elements below their parent element?
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>
z-index doesn't work with ::after/::before element?
You can remove z-index
from parent element and use negative z-index: -1
on pseudo element. If you want only green line on red line you need to remove white background from parent also DEMO
.or { border: 2px solid #8fc300; border-radius: 5px; color: #333; font-size: 17px; font-weight: 600; height: 34px; line-height: 26px; text-align: center; width: 34px; margin-top: 64px; margin-left: 20px; margin-right: 20px; background: #fff; /*For z-index - keep the green area on top*/ position: relative;}.or::after { background: red; content: ""; display: block; height: 116px; margin-left: 15px; margin-top: -68px; width: 4px; /*For z-index - keep the green area on top*/ position: absolute; z-index: -1;}
<div class="or"></div>
z-index when using ::after under element
Your div and its ::after pseudo-element are members of the same stacking context, in this case the root stacking context. The new stacking context you give the pseudo-element would be used as a reference to its children (which are non-existent), but the z-index
value applies to the current stacking context. And the CSS spec dictates the following paint order for each stacking context:
Within each stacking context, the following layers are painted in
back-to-front order:
- the background and borders of the element forming the stacking context.
- the child stacking contexts with negative stack levels (most negative first).
- the in-flow, non-inline-level, non-positioned descendants.
- the non-positioned floats.
- the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
- the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
- the child stacking contexts with positive stack levels (least positive first).
Look, child stacking contexts with negative stack levels, such as your div::after
are painted before the positioned descendants with stack level 0, such as the div
itself. This explains the behavior you noticed.
z-Index behaviour on pseudo elements
You would have to give pseudo elements a negative z-index to get it to go behind it's parent, plus remove the z-index on the parent.
http://jsfiddle.net/jklm313/Kq2PY/4/
div{
position:relative;
background: #000;
padding: 10px;
}
div:after{
content: '';
position: absolute;
z-index: -1; /* <= not working:( */
background: #3d3;
left: 20px;
top: 20px;
width: 30px;
height: 30px;
}
<div>erferf</div>
CSS :after behind parent element
In your website, you have the following CSS rule:
.btn {
position: relative;
z-index: 1;
display: inline-block;
padding: .8rem 1rem;
font-size: 1rem;
background: #000;
-webkit-transition: all 0.2s linear;
-moz-transition: all 0.2s linear;
-o-transition: all 0.2s linear;
transition: all 0.2s linear;
}
If you remove the z-index: 1
property, your CSS will work correctly.
This property is not in the sample snippet that you provided above.
I tried it out using CSS inspector in Firefox and that seems to fix the issue.
z-index on positioned pseudo element (after) not working
If you remove the transform and z-index from .dad, the red square will be under the green square.
Why can't an element with a z-index value cover its child?
There are two important things you need to know: the painting order and the stacking context. If you refer to the specification, you can find how and when elements are painted.
- Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
All positioned, opacity or transform descendants, in tree order that fall into the following categories:
- All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.
- Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.
It's clear from this that we first paint elements with negative z-index
at step (3), then the one with z-index
equal to 0 at step (8), and finally the ones with positive z-index
at step (9), which is logical. We can also read in another part of the specification:
Each box belongs to one stacking context. Each box in a given stacking context has an integer stack level, which is its position on the z-axis relative to other boxes in the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked bottom-to-top according to document tree order.
To understand when each element will be painted you need to know its stacking context and its stack level inside this stacking context (defined by z-index
). You also need to know whether that element establishes a stacking context. This is the tricky part, because setting z-index
will do this:
For a positioned box, the z-index property specifies:
- The stack level of the box in the current stacking context.
- Whether the box establishes a stacking context
Values have the following meanings:
<integer>
This integer is the stack level of the generated box in the current stacking context. The box also establishes a new stacking context.
auto
The stack level of the generated box in the current stacking context is 0. The box does not establish a new stacking context unless it is the root element.
Now we have all the information to better understand each case. If the parent element has a z-index
value of something other than auto
, then it will create a stacking context, thus the child element will be painted inside whatever their z-index
is (negative or positive). The z-index
of the child element will simply tell us the order of painting inside the parent element (this covers your second point).
Now, if only the child element has a positive z-index
and we set nothing on the parent element, then considering the painting order, the child will be painted later (in step (9)) and the parent in step (8). The only logical way to paint the parent above is to increase the z-index
, but doing this will make us fall into the previous case where the parent will establish a stacking context and the child element will belong to it.
There is no way to have the parent above a child element when setting a positive z-index
to the child. Also there is no way to have the parent above the child if we set a z-index
to the parent element different from auto
(either positive or negative).1
The only case where we can have a child below its parent is to set a negative z-index
on the child element and keep the parent at z-index: auto
, thus this one will not create a stacking context and following the painting order the child will be painted first.
In addition to z-index
, there are other properties that create a stacking context. In case you face an expected stacking order, you need to consider those properties, too, in order to see if there is a stacking context created.
Some important facts that we can conclude from the above:
- Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
- Each stacking context is completely independent of its siblings: only descendant elements are considered when stacking is processed.
- Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context. ref
1: there is some hacky ways if we consider the use of 3D transformation.
Example with an element going under its parent element even if this one has a z-index
specified.
.box {
position:relative;
z-index:0;
height:80px;
background:blue;
transform-style: preserve-3d; /* This is important */
}
.box > div {
margin:0 50px;
height:100px;
background:red;
z-index:-1; /* this will do nothing */
transform:translateZ(-1px); /* this will do the magic */
}
<div class="box">
<div></div>
</div>
z-index for pseudo :after not placed under parent element
Remove the z-index
of the parent
That will give the pseudo elements will have their own stacking context (as you have position: absolute
already applied). Here's an updated fiddle. Hope this helps!
Related Topics
How to Toggle Two CSS ':Checked' Pseudo-Classes with One Click
Internet Explorer 11 and Supported Web Fonts
Macos Chrome Horizontal Scrollbar Not Disappearing
How to Add Tooltip to Image on Hover with CSS
Ie 10's -Ms-Clear Pseudo-Element, and Ie5 Quirks Mode
How to Properly Mix Bootstrap and Bem
How to Use a Background Image on the Stroke of an Svg Element
How to Scroll with Ionic and Have Fixed Content Above
Web Design for Smart Phone - Pixel Size
Css: How to Vertically and Horizontally Align an Image
How to Use CSS Attribute Selector for an Svg Element with Namespaced Attribute Href
Resize Unknown Number of Elements to Fill Width of Parent Container
Hide Overflow on Elements with Fixed Position
How to Create a Lollipop Shape by Stacking Divs in a Circular Manner