2.1定位系列——z-index层叠上下文

207 阅读4分钟

本人已参与新人「创作礼活动」,一起开启掘金创作之路。

一、关于z-index的四个思考

● 当一个设置了z-index值的定位元素与正常的文档流中的元素相互重叠的时候,谁会被置于上方?
● 当定位元素与浮动元素相互重叠的时候,谁会被置于上方?
● z-index必须要与定位一起使用才会生效吗?
● z-index大的元素一定会遮挡z-index小的元素吗?

二、z-index的原理

解决上面的问题需要深入理解z-index的原理,需要知道层叠上下文和层叠顺序

1、概念:
层叠上下文就是html中的一个三维概念。相当于在水平面创建了一个z轴,它包含了一组层叠层的元素。我们所创建的每一个网页都有一个默认的层叠上下文,层叠上下文的根就是html,其他的所有元素都会在这个层叠上下文占据一个层叠水平,或高或低。

2、层叠规则与顺序:
● 谁大谁上:在同一个层叠上下文中,层叠水平值大的那一个覆盖层叠水平值小的
● 后来居上:当元素的层叠水平一致、层叠顺序相同的时候,在DOM流中处于后面的元素会覆盖前面的元素
● 最近祖先比较:在不同层叠上下文中,要先找到其各自最近的且处于同层级的祖先,然后采用上面两种方法进行祖先层级水平比较,祖先层级水平高的覆盖祖先层级水平低的;取决于祖先层级水平,不取决于自身
在一个层叠上下文中,有七种层叠顺序:

七种层叠顺序

提示: 页面中内联元素的层叠顺序要比浮动元素和块状元素都高,是因为浮动和块级盒子用来布局,而内联元素用来显示内容;所以比其他两者要高。

三、触发新的层叠上下文

  1. 根元素 <html></html>默认的层叠上下文
  2. position值为 absolute|relative,且 z-index值不为 auto
  3. position 值为 fixed|sticky
  4. z-index 值不为 auto 的flex子元素,且父元素 display:flex|inline-flex;此时,该子元素为层叠上下文元素
  5. opacity 属性值小于 1 的元素
  6. transform 属性值不为 none 的元素
  7. will-change 中指定了任意 CSS 属性,即便你没有直接指定这些属性的值
  8. -webkit-overflow-scrolling 属性被设置 touch的元素
  9. mix-blend-mode 属性值不为 normal 的元素
  10. 元素的filter、 perspective、 clip-path、 mask、 mask-image、 mask-border、 motion-path 值不为 none 的元素
  11. isolation 属性被设置为 isolate 的元素

四、示例代码

  • 示例一:层叠顺序代码验证(遮挡或部分文字重叠遮挡)

image.png

.box { width: 560px; height: 110px; background-color: rgba(255,255,2, 0.9); border: 20px solid red; }
.box .node1 { position: relative; z-index: -1; white-space: nowrap;}
.box .node1 .test1 { position: absolute; z-index: 9999; left: 50px; top: 20px; }
.box .node2 {}
.box .node3 { float: left; color: seagreen; white-space: nowrap; }
.box .node4 { color: blue; }
.box .node5 { position: relative;  z-index: 0; color: rgb(255, 0, 234); top: -21px; left: 296px;}
.box .node6 { position: relative; z-index: 9; color: red; top: -42px; left: 112px;}

<div class="box">
    <span class="node1">
        负的z-indexz-index 为负值时形成的层叠上下文;负的z-indexz-index 为负值时形成的层叠上下文
        <span class="test1">验证:形成新的层叠上下文,定位出去会被遮挡;验证:形成新的层叠上下文,定位出去会被遮挡</span>
    </span>
    <div class="node2">块级盒子: 文档流中正常的块级元素;</div>
    <div class="node3">浮动盒子:非定位的浮动盒子;浮动盒子:非定位的浮动盒子;浮动盒子:非定位的浮动盒子;</div>
    <span class="node4">行内盒:文档流内的行内级盒子; 行内盒:文档流内的行内级盒子</span>
    <div class="node5">文档流内的行XXXX;z-index0 定位元素,这些元素建立了新的层上下文。</div>
    <div class="node6">正的z-index,级别最高,文档</div>
</div>
  • 示例二:relative或absolute定位 + z-index 非auto触发新的层叠上下文 image.png

image.png

/* .box1 { position: relative; z-index: auto; } */
.box1 {  position: relative; z-index: 1; }
.box1 img { position: absolute; z-index: 2; width: 300px; height: 200px; }
/* .box2 { position: relative; z-index: auto; } */
.box2 { position: relative; z-index: 1; }
.box2 img { position: absolute; z-index: 1; width: 200px; height: 300px; }

<div class="box1">
    <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg" alt="">
</div>
<div class="box2">
    <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp05%2F1910021010125G2-0-lp.jpg" alt="">
</div>

image.png

image.png

  • 示例三:fixed、sticky定位触发新的层叠上下文
.box {}
/* .inner { width: 200px; height: 220px; background-color: pink; } */
.inner { position: fixed; width: 200px; height: 220px; background-color: pink; }
img { position: fixed; z-index: -1; width: 300px; height: 180px; }

<div class="box">
    <div class="inner">
        <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg" alt="">
    </div>
</div>
  • 示例四:父元素flex + 子元素z-index 非auto触发新的层叠上下文
/* .box { display: flex; } */
.box { display: flex; }
.inner { width: 200px; height: 220px; z-index: 9; background-color: pink; }
img { position: relative; z-index: -1; width: 300px; height: 180px; }

<div class="box">
    <div class="inner">
        <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg" alt="">
    </div>
</div>
  • 示例五:opacity < 1 触发新的层叠上下文
.box {}
/* .inner { width: 200px; height: 220px; background-color: pink; } */
.inner { opacity: 0.6; width: 200px; height: 220px; background-color: pink; }
img { position: relative; z-index: -1; width: 300px; height: 180px; }

<div class="box">
    <div class="inner">
        <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg" alt="">
    </div>
</div>
  • 示例六:transform 非 none 触发新的层叠上下文
.box {}
.inner { transform: translateX(50px); width: 200px; height: 220px; background-color: pink; }
img { position: relative; z-index: -1; width: 300px; height: 180px; }

<div class="box">
    <div class="inner">
        <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg" alt="">
    </div>
</div>