foreword
z-index
is a property that controls the order of layers in a document. Elements with higher z-index
values will appear above elements with lower values. Just as the x- and y-axes on a page determine the horizontal and vertical position of an element, z-index
controls how they stack on top of each other on the z-axis.
Default stacking order
When we write HTML, elements that appear at the back of the document will naturally cascade on top of the elements at the front.
<body>
<header class="site-header"></header>
<main class="site-content"></main>
<footer class="site-footer"></footer>
</body>
Based on the HTML snippets given above, if their positions overlap each other, footer
will be stacked on top of the main
content area, and main
will be stacked on top of each other header
above.
元素可以通过使用position
e64831c8b9c14b00bb8a956477c5f2a5---属性和偏移属性的组合来进行重叠,偏移属性值包括top
, right
, bottom
and left
.
If you set position: absolute
for each element, they all lay out on top of each other. footer
element appears last in the document, so by default this element is stacked on top of the first two elements.
.site-header, .site-content, .site-footer {
position: absolute;
width: 400px;
padding: 20px;
}
.site-header {top: 0; left: 0;}
.site-content {top: 50px; left: 50px;}
.site-footer {top: 100px; left: 100px;}
If we use the offset properties top
and left
we can see the stacking order more clearly.
stacking context
While using position: absolute
can create elements that overlap each other, we haven't created what's called a stacking context .
Stacking contexts can be created in any of the following ways:
- 元素的
position
absolute
relative
,z-index
值不auto
。 -
flex
a child element of the container, andz-index
value is notauto
. -
opacity
attribute value is less than1
. -
transform
attribute value is notnone
.
By far the most common way to create and use a stacking context is the first in the above list, so let's take a little more time to focus on it.
Going back to the previous example, we have three elements that overlap each other, but so far they have no z-index
value.
z-index
properties allow us to control the order of stacking. footer
元素z-index: 1
, main
元素上z-index: 2
,以及在header
元素上Set z-index: 3
, then the default stacking order will be completely reversed.
On the surface it seems simple, higher z-index
values have higher element stacking order. So z-index: 9999
is always on top of z-index: 9
. Is this really the case? Unfortunately, the actual situation is a bit more complicated.
z-index in stacking context
<header class="site-header blue">header</header>
<main class="site-content green">content
<div class="box yellow"></div>
</main>
<footer class="site-footer pink">footer</footer>
If I add a box
inside the site-content
container, and position it outside the bottom right corner, we can see it's above the green box and below the pink box.
.box {
position: absolute;
bottom: -25px;
right: -25px;
z-index: 4; /* won't work :( */
width: 75px;
height: 75px;
border: 1px solid #000;
}
.site-header {top: 0; left: 0; z-index: -1;}
.site-content {top: 50px; left: 50px;}
.site-footer {top: 100px; left: 100px; z-index: 3;}
Based on what we know z-index
, we might think that in order to make this yellow box appear above the pink box, we can set a higher value for z-index
.
If I set z-index: 4
for the yellow box, the value is higher than z-index: 3
, but I don't see any change. People usually force views to change the stacking order by setting a huge number, say z-index: 9999
, but this has no effect. If you see a value like this z-index
in your project, it's bad code. We want to avoid this behavior as much as possible.
The root cause of the above settings not taking effect is due to the behavior of z-index
in the stacking context.
To demonstrate this, let's look at a slightly more complex example, which I borrowed from the MDN website.
<header class="site-header blue">
<h1>Header</h1>
<code>position: relative;<br/>
z-index: 5;</code>
</header>
<main class="site-content pink">
<div class="box1 yellow">
<h1>Content box 1</h1>
<code>position: relative;<br/>
z-index: 6;</code>
</div>
<h1>Main content</h1>
<code>position: absolute;<br/>
z-index: 4;</code>
<div class="box2 yellow">
<h1>Content box 2</h1>
<code>position: relative;<br/>
z-index: 1;</code>
</div>
<div class="box3 yellow">
<h1>Content box 3</h1>
<code>position: absolute;<br/>
z-index: 3;</code>
</div>
</main>
<footer class="site-footer green">
<h1>Footer</h1>
<code>position: relative;<br/>
z-index: 2;</code>
</footer>
.blue {background: hsla(190,81%,67%,0.8); color: #1c1c1c;}
.purple {background: hsla(261,100%,75%,0.8);}
.green {background: hsla(84,76%,53%,0.8); color: #1c1c1c;}
.yellow {background: hsla(61,59%,66%,0.8); color: #1c1c1c;}
.pink {background: hsla(329,58%,52%,0.8);}
header, footer, main, div {
position: relative;
border: 1px dashed #000;
}
h1 {
font: inherit;
font-weight: bold;
}
.site-header, .site-footer {
padding: 10px;
}
.site-header {
z-index: 5;
top: -30px;
margin-bottom: 210px;
}
.site-footer {
z-index: 2;
}
.site-content {
z-index: 4;
opacity: 1;
position: absolute;
top: 40px;
left: 180px;
width: 330px;
padding: 40px 20px 20px;
}
.box1 {
z-index: 6;
margin-bottom: 15px;
padding: 25px 10px 5px;
}
.box2 {
z-index: 1;
width: 400px;
margin-top: 15px;
padding: 5px 10px;
}
.box3 {
z-index: 3;
position: absolute;
top: 20px;
left: 180px;
width: 150px;
height: 250px;
padding-top: 125px;
text-align: center;
}
Here we have a header
, footer
and main
containers, just like before. But inside site-content
we have three boxes which are all positioned and given z-index
.
Let's first look at the three main containers -- header
, footer
and main
.
header
的z-index
5, z-index
4的main
, footer
The z-index
has a value of 2, so it appears under main
. So far so good, right? very good.
main
Three boxes inside the container make things confusing.
Content box 1's z-index
has a value of 6, but appears below header
, while header
has a value of z-index
.
The value of z-index
of Content box 2 is 1, but it appears above footer
, while the value of footer
b2d91bd8144f24d of z-index
.
What exactly happened?
All doubts can be explained by the fact that all z-index
values are valid in their parent stacking context. Because the parent container .site-content
has a higher z-index
value than footer
.site-content
will be will be calculated in this context.
A good way to think about a stacking order in a stacking context is to think of it as a subitem in a nested ordered list. In this way, it can be written in the following format:
- Header:
z-index: 5
Main:
z-index: 4
- Box 1:
z-index: 4.6
- Box 2:
z-index: 4.1
- Box 3:
z-index: 4.3
- Box 1:
- Footer:
z-index: 2
So even though header
is z-index: 5
and content box 1 is z-index: 6
, the rendering order of content box 1 is 4.6, which is still less than 5. Therefore, content box 1 is under header
.
It was a bit messy at first, but with practice, it started to look better.
z-index only works on positioned elements
If you want to control the stacking order of elements, you can use z-index
for that purpose.但是,只有当该元素的position
3c2a057964432b64e42055589fc4789b---值为absolute
、 relative
fixed
时, z-index
make an impact.
Using position
to precisely place elements is great for building complex layouts or interesting UI patterns. But usually you just want to control the order of the cascade without moving the element away from its original position on the page.
position: relative
这种情况,你可以只设置---db8a01bf6bb45142a033f2546effda36--- ,而不提供top
、 right
、 bottom
left
any value. The element will remain in its original position on the page, the flow of the document will not be interrupted, and the z-index
value will take effect.
z-index can be negative
Layered elements are often used to build complex graphics or UI components. This usually means layering elements on top of each other and setting increasing z-index
values. To place an element below another, it only needs to have a lower z-index
value, but this lower value can be negative.
A negative value of z-index
is useful when using a pseudo-element and wanting to position it after the content of its parent.
Because of the way stacking contexts work, for any :before
or :after
element, if they are to be positioned behind the text content of their parent element, they need a negative z-index
value.
z-index strategy
Let's wrap it up with a simple strategy I've applied in my project z-index
.
Previously, we used single digit increments to set the z-index
value, but if you want to add a new one between the two elements set z-index: 3
and z-index: 4
element, what do you do? You have to change more values at the same time. This can be problematic and prone to breaking CSS in other parts of the site.
Set z-index with 100 steps
When processing z-index
, you often see code like this:
.modal {
z-index: 99999;
}
Code like this looks pretty crude to me, and even worse when !important
is appended. When seeing a value like this, it often means that the developer doesn't understand the stacking context and is trying to force one layer on top of another.
Rather than using arbitrary numbers like 9999, 53, or 12, we systematize our z-index
scale to bring more order to the program. Here I will use the z-index
value in increments of 100.
.layer-one {z-index: 100;}
.layer-two {z-index: 200;}
.layer-three {z-index: 300;}
I do this to keep things organized, but also to pay attention to the many different layers used throughout the project. Another benefit is that if a new layer needs to be added between the other two, there are 99 potential values to pick from.
This manual approach is fairly reliable when building a z-index
system, but can be made more flexible when combined with the capabilities of a preprocessor like Sass.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。