CSS层叠上下文、层叠顺序和层叠等级

0 前言

在讨论层叠上下文和层叠顺序之前先举个例子,创建两个box,其中红色box200px400px,蓝色box400px200px

  <div class="box">
    <div class="blue-box"></div>
  </div>
  <div class="box">
    <div class="red-box"></div>
  </div>
.box {
  position: relative;
  z-index: auto; /* 默认值 */
}

.blue-box {
  width: 400px;
  height: 200px;
  background: blue;
  position: absolute;
}

.red-box {
  width: 200px;
  height: 400px;
  background: red;
  position: absolute;
}

效果如下:
在这里插入图片描述
在此引出两个问题:

  1. 为什么red-boxblue-box之上?
  2. 怎么让blue-boxred-box之上?

1 层叠上下文

1.1 层叠上下文的概念

之所以元素在浏览器中有显示上下之分,是因为浏览器将页面构想成一个3D的坐标轴,而屏幕的正面即为坐标轴的z轴,如图所示:
在这里插入图片描述
每个页面都有一个默认的层叠上下文,根元素html就是一个层叠上下文,而且其中还可能含有其他的层叠上下文,在同一个层叠上下文中,元素出现的上下顺序叫做层叠等级,决定层叠等级的规则叫做层叠顺序。

前面提到根元素html就是一个层叠上下文,并且还可以在其中创建其他层叠上下文,在CSS中每个层叠上下文的层叠层都是独立的,不受其他层叠上下文的影响,如下图所示,跟元素html之中又有三个独立的层叠上下文,三个独立的层叠上下文中各自有自己的层叠层:
在这里插入图片描述

1.2 创建层叠上下文的方法

满足以下任意一种情况即可创建一个层叠上下文:

  • 根元素html(属于被动创建层叠上下文)
  • position值为非static且z-index值不为auto。
  • 弹性盒模型flex中的元素,且z-index值不为auto。
  • opacity属性值小于1的元素。

以上列举的是常见的方法,更多方法可查阅文档MDN-层叠上下文

2 层叠等级

层叠等级决定了同一个层叠上下文中的层叠顺序,并且元素的层叠等级只有在同一个层叠上下文中比较才有意义,如1.1节中三个独立层叠上下文内的ABC三个元素,因为这三个元素属于不同的层叠上下文,所以各自拥有独立的层叠顺序,所以将其比较是没有意义的。

在1.1节中的例子里,ABC三个元素是没有发生位置重叠的,若此时三个元素发生了位置重叠,如下图所示:
在这里插入图片描述
在进行比较时,由于三个元素属于不同的层叠上下文,所以就要找对应父级元素所在的上下文,即要确定redgreenblue三个层叠上下文的层叠等级,因为这redgreenblue都属于根元素html的层叠上下文中,所以能够进行比较,最终根据父级元素的层叠等级来确定三个子元素ABC的显示顺序。

3 被误解的z-index

举个例子如下图所示,redgreenblue之下,所以元素A也在BC之下,那么怎么让A显示在最上面呢?
在这里插入图片描述
相信有人肯定会马上给出答案:给元素A设置CSS样式:z-index: 9999;这样元素A就显示在所有元素之上了。其实这种说法是错误的,这也是很多人对于z-index的误解。

确实,当需要指定不同的排列顺序时,只要给元素指定一个z-index数值,该数值必须是一个整数(正整数和负整数),这个数值表示了元素在z轴的位置,数值越大,元素越在z轴的最上方。但是,z-index的使用是有先决条件的:

  1. z-index只适用于定位的元素,对非定位元素无效,如果一个元素没有指定z-index,那么其默认值是autoz-index0层)。
  2. 元素的z-index值只有在同一个层叠上下文中才有意义。

根据第两个先决条件可知,由于元素ABC不属于同一个层叠上下文,所以即使给元素A设置CSS样式:z-index: 9999;也无法将A元素置于所有元素之上。

4 层叠顺序

当元素发生重叠时,下图描述了7种元素类型对应的层叠顺序:
在这里插入图片描述
在这里插入图片描述
图中的顺序很好理解,但是有几点值得注意:

  1. 内联元素(inline/inline-block)的层叠顺序高于浮动float元素和块级block元素:这个容易理解,网页的重点是显示内容,如内联元素span用于定义文本块,内联元素img用于显示图片,所以理所当然的使这类表示内容的内联元素拥有更高的层叠顺序。
  2. 浮动float元素的层叠顺序高于块级block元素。
  3. 虽说z-index:autoz-index:0在同一层叠顺序,但是两者有着重要的区别:参照1.2节中创建层叠上下文的方法,z-index:auto是不会创建一个新的层叠上下文的,而z-index:0能够创建一个新的层叠上下文。

另外可以通过下面的图片对层叠顺序进行记忆:
在这里插入图片描述
除去z-index相关的层叠顺序,由表示内容的内联元素层叠顺序最高,其次是表示内容布局的浮动元素和块级元素,最后是用于装饰内容的层叠上下文的背景和边框。

5 判断层叠顺序的方法

  1. 在同一个层叠上下文中,其内部元素的层叠顺序按照第4章中的层叠顺序图来排列。
  2. 在同一个层叠上下文中,若两个元素的层叠顺序相同,则后面的元素会在前面的元素之上。
  3. 在不同层叠上下文的情况下比较两个元素的层叠顺序,需要向上查询其父元素所在的层叠上下文,直到两者的某一级父元素在同一层,再比较这两个父级元素的层叠顺序。

6 前言中的问题

在这里插入图片描述
前言中留下了两个问题:

  1. 为什么red-boxblue-box之上?
    a. 首先判断两个两个box是否在同一个层叠上下文中,由于red-boxblue-box都拥有一个父元素box,父元素box中含有非static定位属性,但是z-indexauto,所以父元素box并没有形成单独的层叠上下文,所以这两个box同属于根元素html的层叠上下文中,因此red-boxblue-box也属于同一个层叠上下文。
    b. 此时再判断red-boxblue-box的层叠顺序,由于red-boxblue-box属于同种类型的元素,两者拥有相同的层叠顺序,所以后出现的red-box会位于blue-box之上。
  2. 怎么让blue-boxred-box之上?
    (1)方案一:根据对于问题1的分析,可以将red-boxblue-box互换位置,如下代码,这样blue-box就成为了后出现的元素:
<div class="box">
  <div class="red-box"></div>
</div>
<div class="box">
  <div class="blue-box"></div>
</div>

(2)方案二:由于red-boxblue-box属于同一个层叠上下文,所以可以通过z-index属性将blue-box置于red-box之上,如下代码,给blue-box添加z-index: 2,给red-box添加z-index: 1

.blue-box {
  width: 400px;
  height: 200px;
  background: blue;
  position: absolute;
  z-index: 2; /* 添加z-index */
}

.red-box {
  width: 200px;
  height: 400px;
  background: red;
  position: absolute;
  z-index: 1; /* 添加z-index */
}

(3)方案三:方案一和方案二都是在同一个层叠上下文的条件下,方案三将red-boxblue-box置于两个不同的层叠上下文,修改代码如下:

<div class="box1">
  <div class="blue-box"></div>
</div>
<div class="box2">
  <div class="red-box"></div>
</div>

通过将父级box1box2z-index修改为0而创建了两个单独的层叠上下文。

.box1, .box2 {
  position: relative;
  z-index: 0; /* 创建层叠上下文 */
}

.blue-box {
  width: 400px;
  height: 200px;
  background: blue;
  position: absolute;
  z-index: 2;
}

.red-box {
  width: 200px;
  height: 400px;
  background: red;
  position: absolute;
  z-index: 1;
}

注意:此时red-boxblue-boxz-index还保留了,效果如图:
在这里插入图片描述
可以发现red-boxblue-boxz-index失效了,即使blue-boxz-indexred-box大也无济于事,这也正好验证了关键结论“元素的z-index值只有在同一个层叠上下文中才有意义”。这里之所以red-box还在blue-box之上是因为其父级box在根元素html层叠上下文中的层叠顺序。

所以在这个例子中,想要实现blue-boxred-box之上,需要通过z-index修改box1box2的层叠顺序:

    .box1 {
      position: relative;
      z-index: 1;
    }

    .box2 {
      position: relative;
      z-index: 0;
    }

效果如下:
在这里插入图片描述

7 总结

在实际开发中,需要牢记的内容有:

  1. 创建层叠上下文的方法:MDN-层叠上下文
  2. z-index的使用条件:必须是定位元素且比较z-index的元素在同一个层叠上下文,参阅第3章内容。
  3. 层叠顺序:可以按照如下方法记忆(由高到低):
    a. 正z-index
    b. 默认值z-index:autoz-index:0(注意两者区别,参阅第4章内容)
    c. 表示内容的inline/inline-block
    d. 表示布局的float浮动元素和block块级元素
    e. 负z-index
    f. 表示装饰的层叠上下文的背景和边框
  4. 判断层叠顺序的方法,参阅第5章内容。
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值