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
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>
Need help understanding the stacking layer order of this code that uses the z-index
For the layering order for a HTML page, it will always have the following rules.
- An element will always be in front of it's parent. This does not say anything about other elements inside it.
- The CSS engine will always render higher z-indexes on front of lower z-indexes. If the z-index is not defined, it will act as being 0.
- The elements will render static elements first, then relative, then absolute, then fixed.
- If none of these rules are different, the elements will render on the order as written (first one on background, latest one on foreground).
For layering background images, the first one will render on the foreground and the latest one on the background. The background color will always render before the background image.
CSS z-index and stacking contexts
Now, is it possible to stack the elements in the above demo in the following order (farthest to closest):
#d1, #d4, #d2, #d3
?
No, it is not possible. The farthest you can go is #d1
, #d4
, #d2
with the following:
#d1 { z-index: -1; position: relative; }
#d2 { }
#d3 { }
#d4 { z-index: -1; position: relative; }
... but this results in #d1
creating a stacking context for #d3
, which prevents #d3
from ever being painted above #d2
or #d4
because the negative z-index of #d1
causes #d1
itself to be painted below #d4
(as two boxes with the same stack level will be painted in source order, and #d4
comes after #d1
) and #d2
.
Why does position:relative; appear to change the z-index?
You need to refer to the specification and more precisely the painting order to understand when each layer is painted.
Without position:relative
your element is not positioned and will be painted at the step (4):
- 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:
Then we paint the positioned elements (including the .mask
) at the step (8)
- All positioned, opacity or transform descendants, in tree order that fall into the following categories
Now when you add position:relative
you make the container also positioned thus it will fall in the step (8) too and as described there we consider the tree order since both don't have any z-index
specified. So the .container
will painted later in this case.
If you change the order of the element (you make the container before the mask) you will notice that position:relative
won't have any effect because in both cases the painting order will be the same:
body {
margin: 0;
font-family: arial;
}
section {
position: relative;
background: url(https://preview.webpixels.io/boomerang-v3.6.1/assets/images/backgrounds/slider/img-41.jpg)
no-repeat left center/cover;
height: 70vh;
display: flex;
justify-content: center;
}
.container {
position: relative; /* you can remove this*/
width: 100%;
max-width: 1280px;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
.mask {
position: absolute;
width: 100%;
height: 100%;
background: #3452ff;
opacity: 0.7;
}
<section>
<div class="container">
<h1>Hello World</h1>
</div>
<div class="mask"></div>
</section>
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.
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>
Related Topics
Img Src Svg Changing the Styles With CSS
Vuejs Vue-Router Linking an External Website
Add Footer Text in Each Page of Pdf Using CSS
Select Elements by Attribute in Css
Chrome/Safari Not Filling 100% Height of Flex Parent
Fixed Position But Relative to Container
How to Make Background-Size Work in Ie
Stopping a Css3 Animation on Last Frame
Why Isn't It Possible to Combine Vendor-Specific Pseudo-Elements/Classes into One Rule Set
How to Style the ≪Option≫ With Only Css
Detect If an Input Has Text in It Using CSS - on a Page I Am Visiting and Do Not Control
Child With Max-Height: 100% Overflows Parent
Use of Xsl-Fo, Css3 Instead of Css2 to Create Paginated Documents Like Pdf
Font Awesome 5, Why Is CSS Content Not Showing
Why Are CSS Named Grid Areas Not in Quotes
Play Multiple CSS Animations At the Same Time
Difference Between Display: Inline and Display: Inline-Block