Which CSS properties create a stacking context?
One or more of the following scenarios will cause an element to establish its own stacking context1 for its descendants:
The root element always holds a root stacking context. This is why you can start arranging elements without having to position the root element first. Any element that doesn't already participate in a local stacking context (generated by any of the other scenarios below) will participate in the root stacking context instead.
Setting
z-index
to anything other thanauto
on an element that is positioned (i.e. an element withposition
that isn'tstatic
).Note that this behavior is slated to be changed for elements with
position: fixed
such that they will always establish stacking contexts regardless of theirz-index
value. Some browsers have begun to adopt this behavior, however the change has not been reflected in either CSS2.1 or the new CSS Positioned Layout Module yet, so it may not be wise to rely on this behavior for now.This change in behavior is explored in another answer of mine, which in turn links to this article and this set of CSSWG telecon minutes.
Another exception to this is with a flex item and a grid item. Setting
z-index
will always cause it to establish a stacking context even if it isn't positioned.
Setting
opacity
to anything less than1
.Transforming the element:
Setting
transform
to anything other thannone
.Setting
transform-style
topreserve-3d
.Setting
perspective
to anything other thannone
.
Creating a CSS region: setting
flow-from
to anything other thannone
on an element whosecontent
is anything other thannormal
.In paged media, each page-margin box establishes its own stacking context.
In filter effects, setting
filter
to anything other thannone
.In compositing and blending, setting
isolation
toisolate
and settingmix-blend-mode
to a value different fromnormal
In will change, setting
will-change
to a property whose any non-initial value would create a stacking context.In masking, setting
clip-path
/mask
with a value other thannone
.
Note that a block formatting context is not the same as a stacking context; in fact, they are two completely independent (although not mutually exclusive) concepts.
1 This does not include pseudo-stacking contexts, an informal term that simply refers to things that behave like independent stacking contexts with respect to positioning, but actually participate in their parent stacking contexts.
CSS: Z-Index Stacking Context
Your element need to be at least position:relative
to use z-index as this property doesn't work with static position (the default value)
as you can read here :
Note: z-index only works on positioned elements (position:absolute,
position:relative, or position:fixed).
* { box-sizing: border-box;}
body, html, .container { height: 100%; width: 100%;}
.container { position: fixed; z-index: 300;}
#div1, #div2, #div3 { position:relative; opacity: 0.7; padding: 10px;}
#div1 { border: 1px dashed #996; background-color: #ffc; height: 33.333%; z-index: 1;}
#div2 { border: 1px dashed #900; background-color: #fdd; height: 33.333%; z-index: 2;}
#div3 { border: 1px dashed #696; background-color: #cfc; height: 33.333%; z-index: 3; transform: translateY(-40px)}
<div class='container'> <div id="div1">DIV#1 </div> <div id="div2">DIV#2</div> <div id="div3">DIV#3</div></div>
How to deal with stacking context problem
Since you've created a new stacking context for .parent
, setting z-index
on its children only changes their stacking order relative to other children of the same block. An element can't be layered behind its own stacking context. To put the child behind its parent, let its z-index
work relative to the document (or some other common ancestor that's further up the DOM).
A stacking context is formed... by any...
Element with a position value absolute or relative and z-index value other than auto.
— stacking context
.box {
position: relative;
/* Generate new stacking context here */
}
.parent {
width: 200px;
height: 100px;
background: #168bf5;
margin: 0 0 0 40px;
/* position: relative; */
/* Do not generate new stacking context here */
}
.child {
position: relative;
width: 100px;
height: 200px;
background: #32d19c;
margin: 0 0 0 -40px;
z-index: -1;
}
<div class="box">
<div class="parent">
parent
<div class="child">child</div>
</div>
</div>
When/How does z-index break stacking context?
Every non-positioned box belongs to the same stacking context that's established by the closest ancestor that meets any of the criteria listed here, or the root element if there is no such ancestor. This means that elements don't have to be siblings of one another in order to participate in the same stacking context. They may share a distant ancestor (in HTML, every element descends from the root element), but they don't have to share a parent.
.top
does not establish a new stacking context for its descendants .yes
and .no
as it is non-positioned and its z-index is auto. Therefore, .yes
, .no
and .blocker
all participate in the same stacking context — the root stacking context. As a result the mere fact that .yes
has a higher z-index than .blocker
causes it to be painted in front.
Note that while each of .yes
, .no
and .blocker
does establish its own stacking context, the stacking contexts they establish are not pertinent here; it's the stacking context that they participate in, and they all participate in the same root stacking context.
Understanding z-index stacking order
Basics of the CSS z-index
property
A Simple Concept
The z-index
property is based on a simple concept: Elements with higher values will sit in front of elements with lower values along the z-axis. So if you apply z-index: 1
to div.box1
, and div.box2
has a z-index: 0
, then div.box1
will overlay div.box2
.
In terms of the z-axis, it refers to depth on a three-dimensional plane. On your computer it can be interpreted as the plane on which objects move closer and farther from you. (Learn more about the Cartesian coordinate system.)
Source: Wikipedia
z-index
works on positioned elements
Unless you're dealing with flex items or grid items, the z-index
property works only on positioned elements. This means you can use z-index
on elements with position: absolute
, position: relative
, position: fixed
or position: sticky
. If the element has position: static
(the default value), or some other positioning scheme like a float
, then z-index
will have no effect.
As noted, although z-index
, as defined in CSS 2.1, applies only to positioned elements, flex items and grid items can create a stacking context even when position
is static
.
4.3. Flex Item Z-Ordering
Flex items paint exactly the same as inline blocks, except that order-modified document order is used in place of raw
document order, andz-index
values other thanauto
create a stacking context even ifposition
isstatic
.5.4. Z-axis Ordering: the
z-index
propertyThe painting order of grid items is exactly the same as inline blocks, except that order-modified document order is
used in place of raw document order, andz-index
values other thanauto
create a stacking context even if
position
isstatic
.
Here's a demonstration of z-index
working on non-positioned flex items: https://jsfiddle.net/m0wddwxs/
Stacking Contexts
Once an element is positioned and a z-index
is applied, a stacking context is created.
(Also see: Full list of circumstances where a stacking context is created.)
The stacking context is a set of rules for managing the positioned element with z-index
, and its descendants. These rules govern the placement of child elements in the stacking order and the scope of the property's influence.
Essentially, the stacking context limits the z-index
scope to the element itself, and its child elements cannot affect the stacking order of elements in another stacking context.
If you've ever tried to apply increasingly higher z-index
values only to find that the element never moves out in front, you could be trying to overlay an element in a different stacking context.
Groups of elements with a common parent that move forward or backward
together in the stacking order make up what is known as a stacking
context. A full understanding of stacking contexts is key to really
grasping how z-index and the stacking order work.Every stacking context has a single HTML element as its root element.
When a new stacking context is formed on an element, that stacking
context confines all of its child elements to a particular place in
the stacking order. That means that if an element is contained in a
stacking context at the bottom of the stacking order, there is no way
to get it to appear in front of another element in a different
stacking context that is higher in the stacking order, even with a
z-index of a billion!~ What No One Told You About Z-Index
Stacking Order
CSS adheres to a stacking order when laying out elements on a page. These are the stacking rules when there is no z-index
specified, from farthest to closest:
- Backgrounds and borders of the root element
- Non-positioned, non-floating block elements, in the order they appear in the source code
- Non-positioned floating elements, in the order they appear in the source code
- Inline elements
- Positioned elements, in the order they appear in the source code
If a z-index
property is applied, the stacking order is modified:
- Backgrounds and borders of the root element
- Positioned elements with a
z-index
of less than 0 - Non-positioned, non-floating block elements, in the order they appear in the source code
- Non-positioned floating elements, in the order they appear in the source code
- Inline elements
- Positioned elements, in the order they appear in the source code
- Positioned elements with
z-index
of greater than 0
Source: W3C
Bottom line: Once you understand stacking contexts, z-index
is easy.
For examples of z-index
in action see: How z-index works!
For a brief but highly informative article explaining z-index
(including how opacity
affects the stacking order) see: What No One Told You About Z-Index
For a complete rundown on z-index
, with many examples and illustrations, see: MDN Understanding CSS z-index
And for a deep dive into stacking contexts read: W3C Elaborate description of Stacking Contexts
Do floated elements create a separate stacking context like positioned ones do?
CSS2.1 specifies the painting order of elements as follows:
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).
Floats do not establish stacking contexts on their own. They will only do so if they are positioned and have a z-index that is not auto (not counting any of the numerous other ways an element may do so). Otherwise, they participate in the same stacking context as other elements, including inlines, with the following caveat (from the same link above):
Within each stacking context, positioned elements with stack level 0 (in layer 6), non-positioned floats (layer 4), inline blocks (layer 5), and inline tables (layer 5), are painted as if those elements themselves generated new stacking contexts, except that their positioned descendants and any would-be child stacking contexts take part in the current stacking context.
Since all elements in your fiddle are participating in the same stacking context, and your floating element is not positioned (#4), the inline contents of the overflowing div (#5) are painted above the floating element and its descendant elements, even though the floating element appears later in source order.
The background of the overflowing div (#1) is painted below that of the float, however, because the background of the float is considered part of the float itself in accordance with the second quote above. You can see this by giving the float a negative margin:
#floated {
background-color: pink;
width: 300px;
float: left;
margin-top: -50px;
}
Why does clip-path (and other properties) affect the stacking order (z-index) of elements later in DOM?
From the specifcation:
A computed value of other than none results in the creation of a stacking context the same way that CSS opacity does for values other than 1.
Then considering the painting 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.
For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.
For those with 'z-index: 0' treat the stacking context generated atomically.- All opacity descendants with opacity less than 1, in tree order, create a stacking context generated atomically.
- All transform descendants with transform other than none, in tree order, create a stacking context generated atomically.
The element with clip-path
is painted at the step (8) and the image will be painted before if has no position set
- For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item, or other block equivalent ...
If you add position:relative
to image it will be postioned and will fall under the step (8) and the tree order will decide making it above the clip-path
element
Here is the same code with opacity
where you will have the same painting order:
body {
padding: 1em;
}
header {
background: #a00;
opacity:0.8;
}
h1 {
margin: 0;
padding: 2em;
font: 300%;
color: white;
text-align: center;
}
section {
background: #ccc;
padding-top:5em;
margin-top:-5em;
}
img {
margin-top: -10em;
}
<header>
<h1>Header Content</h1>
</header>
<section>
<img src="https://via.placeholder.com/330/0000FF/808080"/>
</section>
Override CSS Z-Index Stacking Context
We can do it using 3D transformation and we will be able to bring any element to the front even if it's trapped inside a stacking context:
.red,
.green,
.blue {
position: absolute;
width: 100px;
color: white;
line-height: 100px;
text-align: center;
}
body,
div:first-child {
transform-style: preserve-3d; /* this is important for the trick to work */
}
.red {
top: 20px;
left: 20px;
background: red;
/*z-index: 1; we no more need this */
transform:translateZ(1px); /* this will do the trick */
}
.green {
top: 60px;
left: 60px;
background: green;
}
.blue {
top: 100px;
left: 100px;
background: blue;
}
<div><span class="red">Red</span></div>
<div><span class="green">Green</span></div>
<div><span class="blue">Blue</span></div>
Can someone explain stacking contexts?
I found the article you linked by Phillip Walton to be most helpful to me understanding stacking contexts... I went on this study safari in the course of debugging an issue of my own.
Note that the pink square with z-index: 100;
appears below the light blue square with z-index: 1;
because it's constrained by a stacking context created on .A
by the transform
.
This jsbin is a bit easier to experiment with than the SO inline code: https://jsbin.com/lataga/2/edit?css,output
div { width: 200px; height: 200px; padding: 1rem;}
.A { position: absolute; background-color: red;
/* Adding a transform here creates a new stacking context for the children of .A */ transform: translateX(0);
/* several other properties can trigger creation of stacking context, including opacity < 1 */ /* opacity: 0.99; */
/* If we raise .A above .B, the children will rise up with it; uncomment the following to see: */ /* z-index: 3; */}
.a { position: relative;
/* even a much higher z-index can't lift .a above .b when it is constrained to a lower stacking context */ z-index: 100;
margin-left: 125px; background-color: pink;}
.B { position: absolute; margin-top: 75px; /* z-index: 2; */ background-color: blue;}
.b { margin-left: 50px; background-color: lightblue;
/* The following is not necessary: if a z-index is not specified, then it is calculated according to the rules of natural stacking order... I'm just specifying it explicitly for editorial effect. */ z-index: 1;}
<div class="A"> A: 1 <div class="a">a: 1.100</div></div><div class="B"> B: 2 <div class="b">b: 2.1</div></div>
Related Topics
Css Text-Overflow in a Table Cell
How to Hide an Element When Printing a Web Page
Css3 Selector :First-Of-Type With Class Name
Svg Data Image Not Working as a Background-Image in a Pseudo Element
Does "Display:None" Prevent an Image from Loading
Stopping a Css3 Animation on Last Frame
Is There a CSS Hack to Affect Safari Only Not Chrome
Css3 Background Image Transition
Understanding Z-Index Stacking Order
Css3 Nth of Type Restricted to Class
Make a Div Fill an Entire Table Cell
Angular 5 - Failed to Load Resource: the Server Responded With a Status of 404 (Not Found)
Angular Material Mat-Drawer in Full Height Flex, Content Overflow Auto
How to Remove Border of Drop Down List:Css
Spring Boot + Thymeleaf CSS Is Not Applied to Template