Skip to content

一、CSS 中的层叠上下文

TIP

深入浅出 CSS 中的层叠上下文

1、什么是“层叠上下文”

TIP

层叠上下文(stacking context),是 HTML 中一个三维的概念。

  • 在 css2.1 规范中有明确强调,每个 css 盒模型都是处在一个三维空间里面,他们分别处在平面的 X 轴,Y 轴以及表示层叠的 Z 轴。

  • 如下图所示的三个盒子,他们分别在处在 X 轴 和 Y 轴,同时在 Z 轴 上发生层叠。 ![[Pasted image 20260228123345.png]] 但我们都知道,默认情况下,HTML 元素在页面是沿 X 轴 和 Y 轴 平铺。所以并不是所有的盒子都会在Z 轴发生层叠。 如下图所示:元素默认从上往下,从左往右依次排列。所以我们察觉不到它们在 Z 轴 上的层叠关系。 ![[Pasted image 20260228123437.png]] TIP

而一旦元素发生堆叠,我们就会感受到一个元素覆盖了另一个元素,这时我们就能感受到Z 轴的存在。但是实事上,不管元素发不发生重叠,Z 轴都存在。

理解了上面内容之后,那我们回过头来理解下,到底什么是层叠上下文? 你可以把层叠上下文理解为 HTML 元素的一个属性,一但 HTML 元素拥有了这个属性,我们可以理解为这个 HTML 元素在Z 轴上就“高人一等”,也就是在 Z 轴上会显示在更上一层,。 怎么个具象化法理解 ?

你可以把「层叠上下文」理解为当官:网页中有很多很多的元素,我们可以看成是真实世界的芸芸众生。真实世界里,我们大多数人是普通老百姓们,还有一部分人是做官的官员。OK,这里的“官员”就可以理解为网页中的层叠上下文元素。

换句话说,页面中的元素有了层叠上下文,就好比我们普通老百姓当了官,一旦当了官,相比普通老百姓而言,离皇帝更近了。 同理,当元素有了层叠上下文,就相当于他比网页中其它元素的级别更高了,在 Z 轴上的位置就就高了,离我们用户(屏幕)更近了,显示在更上一层。

2、层叠上下文的创建

TIP

层叠上下文也基本上是有一些特定的 CSS 属性创建的。

怎么个具象化法理解?

你可以把这些特定的 CSS 属性,比喻成古代官员的玉佩。如何判定你是当官,那就看你有没有对应的玉佩,拥有不同类型的玉佩,就表明你是此类官员,你就比普通老百姓高人一等

层叠上下文,主要由以下 3 种

  • html 根元素:页面根元素天生具有层叠上下文,称之为“根层叠上下文”。

  • 定位元素的传统层叠上下文(z-index 值为数值时才会创建层叠上下文,z-index:auto 不会创建层叠上下文)。

  • 其他一些 CSS3 属性,可以创建层叠上下文

2.1、根层叠上下文

TIP

指的是页面根元素,也就是页面滚动条的默认的始作俑者 <html>元素。

  • 这就是为什么,绝对定位元素在 left / top 等值定位的时候,如果没有其他定位元素限制,会相对浏览器窗口或 body 定位的原因。

  • 我们写在 body 中的 HTML 标签,默认的就是处在 HTML 这个根层叠上下文中,在这个层叠上下文中各元素在Z 轴上有着自己的排列顺序,具体如何排列,后面层叠顺序会讲到。

2.2、定位元素的传统层叠上下文

TIP

  • 对于包含有 position:relative/ position:absolute的定位元素,当其 z-index值不是 auto的时候,会创建层叠上下文。

  • position值为 fixed(固定定位)或 sticky(粘滞定位)的元素

温馨提示

当我们给元素添加定位 和 z-index时,元素就会显示在其它元素的上面,本质就是因为他拥有了自己的层叠上下文,在 Z 轴上要比其它未拥有层叠上下文的元素更高一等。

2.3、CSS3 与新时代的层叠上下文

TIP

当元素添加以下 CSS3 属性时,元素会创建自己的层叠上下文

如下:

  • z-index值不为 autoflex项(父元素 display:flex|inline-flex

  • 元素的 opacity值不是 1

  • 元素的 transform值不是 none

  • 元素 mix-blend-mode值不是 normal

  • 元素的 filter值不是 none

  • 元素的 isolation值是 isolate

  • will-change指定的属性值为上面任意一个

  • 元素的 -webkit-overflow-scrolling设为 touch

3、什么是层叠顺序

我们都知道

除了定位的元素会覆盖在其它元素的上面之外,还有很多情况下元素会发生重叠,那发生重叠时元素是以什么样的顺序来重叠的呢?这就是我们接下来要讲的元素的层叠顺序。

  • “层叠顺序”英文称作"stacking order",表示元素发生层叠时候有着特定的垂直显示顺序。

  • 我们页面中的元素有: 块级元素,行内元素,行内块元素,浮动元素,定位元素,还有后面学到的一些 CSS3 属性,当元素添加相关属性后,元素的层级也会发生改变。

以下图只列出了目前学到的相关元素,在同一层叠上下文中的层叠顺序。 ![[Pasted image 20260228123819.png]] 同一层叠上下文,元素的层叠顺序,参考上图,由上到下分别

背景和边框:建立当前层叠上下文元素的背景和边框。 负的 z-index:当前层叠上下文中,z-index 属性值为负的元素。 块级盒:文档流内非行内级非定位后代元素。 浮动盒:非定位浮动元素。 行内盒:文档流内行内级非定位后代元素。 z-index:0;层叠级数为 0 的定位元素。 正z-index:z-index属性值为正的定位元素。

3.1、案例 1:当元素都处在 html 层叠上下文中时

<style>

    html{
        background-color: #ddd;
    }
    body {
        margin: 0;
    }
    .container {
        width: 400px;
        height: 600px;
        background-color: rgba(0,0,0,.5);
        margin: 50px;
        position: relative; /* 相对定位 */
        /* z-index: auto;  不会创建自己的层叠上下文 */
        /* z-index:0; 会创建自己的层叠上下文 */
    }
    .box {
        width: 300px;
        height: 100px;
    }
    .box1 {
        background-color: orchid;
        position: absolute;
        z-index: -1;
        top: -20px;
        left: -20px;
    }
    .box2 {
        background-color: aquamarine;
        margin-left: 20px;
    }
    .box3 {
        background-color: pink;
        float: left;
        margin-top: -50px;
        margin-left: 30px;
    }
    .box4 {
        background-color: khaki;
        display: inline-block;
        margin-left: 50px;
        margin-top: -50px;
    }
    .box5 {
        background-color: orange;
        position: absolute;
        left: 110px;
        top: 180px;
        z-index: 0;
    }
    .box6 {
        background-color: rgb(225, 55, 197);
        position: absolute;
        left: 90px;
        top: 260px;
        z-index: 1;
    }
</style>
</head>
<body>
    <div class="container">
        <!-- 定位 z-index:-1 -->
        <div class="box box1">定位 z-index:-1</div>
        <!-- 块级元素 -->
        <div class="box box2">block块元素</div>
        <!-- 浮动元素 -->
        <div class="box box3">float浮动元素</div>
        <!-- 行内块级元素 -->
        <div class="box box4">行内块级元素</div>
        <!-- 定位元素 z-index:0 -->
        <div class="box box5">定位元素 z-index:0</div>
        <!-- 定位元素 z-index:1 -->
        <div class="box box6">定位元素 z-index:1</div>
    </div>
</body>

以上代码中的所有元素都处在 html 根层叠上下文中

![[Pasted image 20260228124113.png]] 你可以修改上面的代码,在 .container 选择器中的添加 z-index:0 。此时,.container 元素会创建自己的层叠上下文,最终所有.container 中的子元素都在 .container 元素所创建的层叠上下文中。

.container {
  /* 省略部分代码,具体见前面 */
  /* z-index: auto;   默认值 不会创建自己的层叠上下文 */
  z-index: 0; /* 会创建自己的层叠上下文 */
}

最终显示效果如下 ![[Pasted image 20260228124200.png]] 重点提示:

如果元素的等级一样,则写在后面的会覆盖在前面的上面。 如块级和块级,浮动和浮动,行内块与行内块,定位与定位元素,发生重叠时,默认的写在后面的会在最上面显示

3.2、案例 2:当元素处在定位元素的层叠上下文中

TIP

当相对定位元素处在 html 层叠上下文中,设置 z-index:-1 时,元素会在所有元素的下面显示。 当相对定位元素处在定位元素( z-index>=0 )的层叠上下文中,设置 z-index-1;时,元素会在当前层叠上下文元素中所有元素的最下面。

<style>
  .box,
  .item {
    width: 100px;
    height: 100px;
  }
  /*box为创建层叠上下文元素*/
  .box {
    background-color: skyblue;
    border: 10px solid khaki;
    position: relative;
    z-index: 0; /*创建层叠上下文-关键代码*/
    /* z-index: auto; 不会创建自己的层叠上下文 */
  }
  .item {
    background-color: pink;
    position: relative;
    top: 50px;
    left: 50px;
    /*元素的层级*/
    z-index: -1;
  }
</style>
<body>
  <div class="box">
    <div class="item"></div>
  </div>
</body>
.box 添加 z-index:0; 创建层叠上下文 .box 未添加 z-index 属性
![[Pasted image 20260228124316.png]] ![[Pasted image 20260228124323.png]]

3.3、案例 3:不同层叠上下文中的子元素层叠顺序

TIP

如下图的 B 和 C 都创建了自己的层叠上下文,那 B 中的子元素和 C 中的子元素的层叠顺序是怎么样的?

如果 C 在 B 的上面,那 C 中所有子元素都会在 B 的子元素上面显示 如果 C 在 B 的下面,那 C 中所有子元素都会在 B 的子元素下面显示 怎么个具象化法理解 ?

就好比 B 的官位高于 C,则 B 家里的所有人(包括丫鬟、门卫) 都要比 C 家中所有的人高人一等。下人的等级本质是由他们所在的官家的等级决定的。 ![[Pasted image 20260228124347.png]]

<style>
  .container {
    width: 400px;
    height: 500px;
    background-color: rgb(221, 219, 219, 0.7);
  }
  .box {
    width: 200px;
    height: 200px;
    position: relative;
    z-index: 0;
    /* 如果z-index为-1,他处在html层叠上下文中,其会显示在当前上下文的块级元素的下面显示 */
    /* z-index: -1;*/
  }
  .box1 {
    background-color: pink;
    /* 
            当z-index值为2时,box1在.box2上面
            其box1的子元素永远在box2上面 
        */
    /* z-index: 2; */
  }
  .box2 {
    background-color: skyblue;
    top: -50px;
    left: 20px;
  }
  .item {
    width: 100px;
    height: 100px;
    position: absolute;
  }
  .item1 {
    background-color: orange;
    top: 100px;
    left: 50px;
    z-index: 22;
  }
  .item2 {
    background-color: chartreuse;
    top: -20px;
    left: 20px;
    z-index: 2;
  }
</style>
<body>
  <div class="container">
    <div class="box box1">
      <div class="item item1"></div>
    </div>
    <div class="box box2">
      <div class="item item2"></div>
    </div>
  </div>
</body>

.box 加 z-index:0;创建自己的层叠上下文,效果如下 ![[Pasted image 20260228124423.png]] .box 未添加 z-index 属性,未创建自己的层叠上下文,效果如下: ![[Pasted image 20260228124437.png]] 如果.box 的 z-index 的值为-1,则.box 中的所有内容都会在灰色块下面显示 ![[Pasted image 20260228124452.png]]

4、如何确定两个元素的层叠顺序

TIP

  • 在比较两个元素的层叠顺序时,会先比较他们所在的层叠上下文的层叠顺序

  • 如果他们所在的同一层叠上下文,则按同一层叠上下文中的元素排列顺序来计算。

  • 如果不在同一层叠上下文中,则他们所在层叠上下文的顺序决定了他们的顺序及其后代元素的层叠上下文顺序。

    • 即 A 层叠上下文要高于 B 层叠上下文,则 A 中的所有子孙元素都会高于 B 中的所有子孙元素。B 中子孙元素的 z-index再大也没有办法在层级上高于 A 元素中子元素。,因为 z-index只能控制同一层叠上下文中的元素堆叠关系。

5、总结:层叠上下文

TIP

  • 什么是层叠上下文

    • 层叠上下文理解为 HTML 元素的一个属性,一但 HTML 元素拥有了这个属性,我们可以理解为这个 HTML 元素在 Z 轴上就“高人一等”,也就是在 Z 轴上会显示在更上一层。
  • 如何创建层叠上下文

    • html 根层叠上下文(默认的,不需要创建)

    • 定位元素的传统层叠上下文(如何创建,见前面)

    • css3 与新时代的层叠上下文(如何创建,见前面)

  • 同一层叠上下文中,元素的层叠顺序

    • z-index可以调节同一层叠上下文中 定位元素的层叠顺序
  • 如何确定两个元素的层叠顺序