头图

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---属性和偏移属性的组合来进行重叠,偏移属性值包括toprightbottom 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 relativez-index值不auto
  • flex a child element of the container, and z-index value is not auto .
  • opacity attribute value is less than 1 .
  • transform attribute value is not none .

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: 1main元素上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 .

headerz-index 5, z-index 4的mainfooter 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
  • 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---值为absoluterelative 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--- ,而不提供toprightbottom 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.


chuck
300 声望41 粉丝