乐趣区

关于css:掌握CSS中的zindex

前言

z-index是一个用于管制文档中图层程序的属性。具备较高 z-index 值的元素将会呈现在具备较低值的元素之上。就像页面上的 x 轴和 y 轴决定一个元素在程度和垂直方向上的地位一样,z-index管制它们在 z 轴上互相层叠的形式。

默认层叠程序

当咱们编写 HTML 时,呈现在文档靠后地位的元素,会天然层叠到靠前地位的元素之上。

<body>
    <header class="site-header"></header>
    <main class="site-content"></main>
    <footer class="site-footer"></footer>
</body>

基于下面给定的 HTML 片段,如果它们的地位互相重叠的话,footer将会层叠在 main 内容区域之上,main将会层叠在 header 之上。

元素能够通过应用 position 属性和偏移属性的组合来进行重叠,偏移属性值包含 toprightbottom 以及left

如果为每个元素设置 position: absolute,他们都会在彼此的根底上进行布局。footer 元素在文档中最初呈现,因而默认状况下,该元素会层叠在前两个元素之上。

.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;}

如果应用偏移属性 topleft,咱们能够更分明地看到层叠程序。

层叠上下文

尽管应用 position: absolute 能够创立互相重叠的元素,但咱们还没有创立所谓的 层叠上下文

层叠上下文能够通过以下任意形式进行创立:

  • 元素的 position 属性值为 absolute 或者 relative,且z-index 值不为auto
  • flex容器的子元素,且 z-index 值不为auto
  • opacity属性值小于 1 的元素。
  • transform属性值不为 none 的元素。

到目前为止,最常见的创立和应用层叠上下文的形式是上述列表中的第一种,所以让咱们多花点工夫来关注它。

回到先前的示例,咱们有三个元素彼此重叠,但目前为止它们并没有 z-index 值。

z-index属性容许咱们管制层叠的程序。如果在 footer 元素上设置 z-index: 1,在main 元素上设置 z-index: 2,以及在header 元素上设置z-index: 3,那么默认层叠程序将会齐全颠倒。

外表上看起来很简略,更高的 z-index 值有更高的元素层叠程序。因而 z-index: 9999 总是位于z-index: 9 下面。事实果真如此吗?可怜的是,理论状况要更简单一些。

层叠上下文中的 z -index

<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>

如果我在 site-content 容器内增加一个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;}

基于咱们所理解的 z-index,咱们可能会认为,为了使这个黄色的盒子呈现在粉色盒子的上方,咱们能够为z-index 设置一个更高的值。

如果我为黄色盒子设置了 z-index: 4,该值要比z-index: 3 高,然而并没有看到任何变动。人们通常视图通过设置一个微小的数字来强制扭转层叠程序,比如说设置z-index: 9999,但这样做没有任何成果。如果在我的项目中看到这样的z-index 值,那就属于坏代码。咱们要尽量避免这种行为。

导致上述设置不失效的根本原因,是因为 z-index 在层叠上下文中的行为。

为了演示这一点,让咱们来看一个略微简单一点的例子,这是我从 MDN 网站上借鉴来的。

<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;
}

在这里,咱们有一个 headerfootermain容器,就跟以前一样。然而在 site-content 外部,咱们有三个盒子,它们都被定位了,并赋予了z-index

让咱们首先看一下三个次要容器 – headerfootermain

headerz-index 值为 5,因而呈现在 z-index 值为 4 的 main 之上,footerz-index 值为 2,因而呈现在 main 之下。目前为止一切顺利吧?很好。

main容器内的三个盒子让事件变得错综复杂起来。

Content box 1 的 z-index 值为 6,但呈现在 header 上面,而 headerz-index值为 5。

Content box 2 的 z-index 值为 1,但呈现在 footer 下面,而 footerz-index值为 2。

这到底产生了啥?

所有疑虑都能够通过以下事实来解释:所有的 z-index 值都是在其父级层叠上下文中失效的。因为父容器 .site-content 相比 footer 而言,有一个更高的 z-index 值,因而 .site-content 中的任何定位元素都将在该上下文中计算。

在层叠上下文中思考层叠程序的一个好办法是,把它看作是嵌套有序列表中的一个子项目。依照这种思路能够写成如下格局:

  • 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

因而,即便 headerz-index: 5,content box 1 是 z-index: 6,但 content box 1 的渲染程序是 4.6,依然小于 5。因而,content box 1 在header 上面。

刚开始的确有点乱,但随着练习,开始有眉目了。

z-index 只作用于定位元素

如果你想管制元素的层叠程序,你能够应用 z-index 达到目标。然而,只有当该元素的 position 值为 absoluterelativefixed时,z-index才会产生影响。

position 准确地搁置元素,对于建设简单的布局或乏味的 UI 模式来说是不错的。但通常只是想要管制层叠的程序,而不把元素从它在页面上的原始地位移开。

如果是这种状况,你能够只设置 position: relative,而不提供toprightbottomleft的任何值。该元素将放弃在其在页面上的原始地位,文档流不会被打断,z-index值将会失效。

z-index 能够是负值

分层元素通常是为了建设简单的图形或 UI 组件。这通常意味着将分层元素彼此重叠,并设置一直减少的 z-index 值。要把一个元素放在另一个元素的上面,它只须要有一个较低的 z-index 值,但这个较低的值能够是负值。

当应用伪元素并心愿将其定位在其父元素的内容之后时,负值的 z-index 是十分有用的。

因为层叠上下文的工作形式,对于任何 :before:after元素,如果它们要被定位在其父元素的文本内容前面,那么它们须要一个负的 z-index 值。

z-index 策略

让咱们用我在我的项目中利用 z-index 的一个简略策略来总结一下。

以前,咱们应用个位数递增来设置 z-index 值,但如果你想在两个设置了 z-index: 3z-index: 4 的元素之间增加一个新的元素,你该怎么办?你必须同时扭转更多的值。这可能会成为问题,并容易在网站的其余局部毁坏 CSS。

应用 100 步长设置 z -index

在解决 z-index 时,常常会看到这样的代码:

.modal {z-index: 99999;}

这样的代码对我来说十分毛糙,当附加上 !important 时,会更加蹩脚。当看到这样的值时,往往意味着开发者不理解层叠上下文,并试图强制一个层在另一个层的下面。

与其应用像 9999、53 或 12 这样的任意数字,不如使咱们的 z-index 比例系统化,为程序带来更多秩序。这里我将应用以 100 为根底进行递增的 z-index 值。

.layer-one {z-index: 100;}
.layer-two {z-index: 200;}
.layer-three {z-index: 300;}

我这样做是为了放弃事件的条理性,同时也是为了留神整个我的项目中应用的泛滥不同的层。另一个益处是,如果须要在其余两个图层之间增加一个新的图层,有 99 个潜在的值能够筛选。

当建设一个 z-index 零碎时,这种手动办法是相当牢靠的,但当与像 Sass 这样的预处理器的能力相结合时,能够变得更加灵便。

退出移动版