当前位置:网站首页 > 后端开发 > 正文

重新理解z-index

一,前言

今天遇到一个布局兼容问题,调试了一番,发现z-index的表现和自己的认知不相符,才知道自己对z-index的认知有错误,于是写篇文章总结下这个z-index的具体使用。有基础的朋友可以直接看第四节。

二,标准文档流

在了解z-index之前,需要先知道标准文档流。

标准文档流其实是浏览器渲染页面的一个规则:所有的页面元素,都要按照它在HTML文档中出现的先后顺序,依次在浏览器中,从左上角开始,从上到下,从左到右的顺序依次显示。

具体的表现为:

2.1,块级元素:

有以下的几个特征:

 1.单独的占一行 2.可以设置宽、高 3.如果不设置宽度,他将默认占满父盒子的宽度 
2.2,行内元素:
 1.与其他元素自动的并排在一行上 2.不能设置它的宽和高,它的宽和高就是内容的宽和高 
2.3,块级元素和行内元素可以相互转换:
 display:block display:inline 

三,position

常见的使元素脱离文档流的手段有:浮动和定位。

之所以讲这个,是因为只有脱离了文档流,才有z-index来设置元素的层叠等级。

浮动好理解,定位主要是position的几个属性值:

通常情况下, position 有以下几个取值。具体如下:

取值 含义 说明
static 静态定位 对象遵循标准文档流,toprightbottomleft 等属性失效。
relative 相对定位 对象遵循标准文档流中,依赖toprightbottomleft 等属性相对于该对象在标准文档流中的位置进行偏移,同时可通过 z-index 定义层叠关系。
absolute 绝对定位 对象脱离标准文档流,使用 toprightbottomleft 等属性进行绝对定位(相对于 static 定位以外的第一个父元素进行绝对定位) ,以及可通过 z-index 定义层叠关系。
fixed 固定定位 对象脱离标准文档流,使用 toprightbottomleft 等属性进行绝对定位(相对于浏览器窗口进行绝对定位)同时可通过 z-index 定义层叠关系。
sticky 粘性定位 可以说是相对定位 relative 和固定定位 fixed 的结合。元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于 viewport 来计算元素的偏移量。

这些内容,网上很多文章都有,不再赘述,本文主要讲解z-index的规则,不忘初心。

四,z-index的层叠上下文理解

z-index应该这样理解:每一个层叠上下文就是一层楼,而该楼层的z-index就是楼梯。1楼层的楼梯值再大,也不可能比2层楼高。

于是我们首先要理解一个层叠上下文的生成条件:

1,根元素html ;
2,绝对定位 absolute 或相对定位 relative 且 z-index 值不为 auto ;
3,一个 flex 项目,且 z-index 值不为 auto ,也就是父元素 display: flex|inline-flex ;
4,元素的 opacity 属性值小于 1 ;
5,元素的 transform 属性值不为 none ;
6,元素的 mix-blend-mode 属性值不为 normal ;
7,元素的 isolation 属性被设置为 isolate ;
8,在 mobile WebKit 和 Chrome 22+ 内核的浏览器中,position: fixed 时总是会创建一个新的层叠上下文, 即使 z-index 的值是 auto ;
元素的 -webkit-overflow-scrolling 属性被设置 touch 。

后面几个比较少用暂且不谈,本文主要讲前几个。需要理清几个名词概念:

层叠上下文:对应本节中所说:生成的一个层叠上下文(一个楼层) 层叠等级:一个层叠上下文中的元素层叠规则:七层层叠规则 层叠上下文层级;每个层叠上下文之间是有级别的,低级别的无论z-index多大都无法突破高级别的层叠上下文。各个层叠上下文之间,用层级来描述(有的文章还是用层叠等级,这样容易混乱,所以我换种说法) 

五,z-index的层叠等级

理解了层叠上下文还不够,因为每层层级上下文内还分为七个层叠等级。具体如下图:

请添加图片描述

如下代码,就能体现出这七层结构:

<!DOCTYPE html> <html lang="en"> <body> <style> body{ 
      height: 100vh; background: pink; } /* 新创建一个层叠上下文 */ .box{ 
      height: 350px; background: greenyellow; position: relative; z-index:1; } .total{ 
      height: 100px; width: 300px; text-align: center; position: absolute; } .first-item{ 
      background: yellow; top: 10px; left:10px; z-index: -1; } .second-item{ 
      background: blueviolet; display: block; top: 40px; left:40px; } .third-item{ 
      background: red; float: left; top: 70px; left:70px; } .fourth-item{ 
      background: blue; display: inline; top: 100px; left:100px; } .five-item{ 
      background: rgb(18, 248, 217); top: 130px; left:130px; z-index: auto; } .six-item{ 
      background: rgb(248, 83, 18); top: 160px; left:160px; z-index: 1; } </style> <div class="box"> <div class="first-item total">z-index小于0 </div> <div class="second-item total">block块级盒子</div> <div class="third-item total">float浮动盒子</div> <div class="fourth-item total">inline/inline-block水平盒子</div> <div class="five-item total">z-index:auto或0或不设置</div> <div class="six-item total">z-index大于0</div> </div> </body> </html> 

实现的效果和七层结构如出一辙:

请添加图片描述

如上文第四节创建层叠上下文的知识可知,这里html默认会创建一个基础的层叠上下文。为了避免它的影响,我这里让box再创建一个层叠上下文(有定位且有z-index)。

于是这六个子元素和自身的background/border其实都在这个box的层叠上下文中,就得遵守同一层叠上下文的七层层叠等级规则。

六,层叠上下文层级和dom结构关系

首先需要明确的一点是层叠上下文层级和dom结构没有明确的映射关系。但层叠上下文层级又基于dom结构生成。

主要是因为层叠上下文支持嵌套,在一个层叠上下文中还可以创造新的层叠上下文。但当未创建新的层叠上下文时,不管dom结构是不是父子关系,都是在同一层叠上下文之间,用七层层叠等级规则执行判断。

这里将上文的代码修改为:

<!DOCTYPE html> <html lang="en"> <body> <style> body{ 
      height: 100vh; background: pink; } /* 新创建一个层叠上下文 */ .box{ 
      height: 350px; background: greenyellow; position: relative; z-index:1; } .total{ 
      height: 100px; width: 300px; text-align: center; position: absolute; } .first-item{ 
      background: yellow; top: 10px; left:10px; } .second-item{ 
      background: blueviolet; display: block; top: 50px; left:40px; z-index: 1; } .a-1{ 
      background: red; height: 20px; position:absolute; left: 200px; top:30px; z-index: 5; } .a-2{ 
      background: rgb(229, 20, 236); height: 20px; position: absolute; z-index: -1; right: -20px; top: 27px; } </style> <div class="box"> <div class="first-item total"> <div class="a-1">a-1</div> <div class="a-2">a-2</div> </div> <div class="second-item total"></div> </div> </body> </html> 

实现的效果:

请添加图片描述

就像这里,box创建了一个新的层叠上下文,又因为它具备子元素first-item和second-item,所以这两个元素必然是在同一个层叠上下文(box创建的)中。

而second-item不再有子元素,不用继续考虑,接下来看first-item。

因为first-item并没有创建新的层叠上下文(虽然有定位,但z-index未设置),则它的子元素也和它一样在当前box创建的层叠上下文中

也就是说,first-item和second-item,a-1以及a-2这四者是在同一个层级上下文中进行堆叠,即使a-1和a-2是first-item的子元素。

于是根据七层层叠规则得到:

box:创建该层叠上下文,它的background在最下面(草绿色) first-item:block块级盒子(黄色) second-item:z-index=1(紫色) a-1:z-index=5(红色) a-2:z-index=-1(粉色) 

这个和上图中结果一致。这就是为啥说:dom结构和层叠上下文没有严格的映射关系。并不是一层dom就生成一个层叠上下文。

另外,层叠上下文层级又基于dom结构生成。意思就是低层级的层叠上下文,无论内部元素的z-index多大,是无论如何无法盖在高层级别元素上方的。

<!DOCTYPE html> <html lang="en"> <body> <style> body{ 
      height: 100vh; background: pink; } /* 新创建一个层叠上下文 */ .box{ 
      height: 350px; background: greenyellow; position: relative; z-index:1; } .total{ 
      height: 100px; width: 300px; text-align: center; position: absolute; } .first-item{ 
      background: yellow; top: 10px; left:10px; z-index: 1; } .second-item{ 
      background: blueviolet; display: block; top: 50px; left:40px; z-index: 2; } .a-1{ 
      background: red; height: 20px; position:absolute; left: 200px; top:30px; z-index: 5; } .a-2{ 
      background: rgb(229, 20, 236); height: 20px; position: absolute; z-index: -100; right: -20px; top: 27px; } </style> <div class="box"> <div class="first-item total"> <div class="a-1 total">a-1</div> <div class="a-2 total">a-2</div> </div> <div class="second-item total"></div> </div> </body> </html> 

对应实现的效果和层叠上下文层级关系如下图,first-item的层级比second-item低,比box高,因此,first-item中的元素无论z-index设置多高,都无法超过second-item的内容。无论z-index设置多低,都无法低于box(草绿色),甚至无法低于创建该层叠上下文的背景色(该层叠上下文中层叠等级最低,下图黄色)。

请添加图片描述

七,判断元素层叠顺序的套路

理解了层叠上下文,层叠等级,层叠上下文层级三者的关系,就可以用这个来判断两元素的遮盖情况:

1,看两个元素所在的层叠上下文层级。高层元素必然遮盖低层元素。 2,若在同一层叠上下文层级,也就是在同一个层叠上下文中,就需要看七层层叠等级。谁高谁在上面 3,如果都一样,后写的盖住之前写的。 

八,案例练习

8.1,多层dom结构,但实际是同一层级上下文的情况
<!DOCTYPE html> <html lang="en"> <body> <style> body{ 
      height: 100vh; background: pink; } /* 新创建一个层叠上下文 */ .box{ 
      height: 350px; background: greenyellow; position: relative; z-index:1; } .total{ 
      height: 100px; width: 300px; position: absolute; } .first-item{ 
      background: yellow; top: 10px; left:10px; } .a-1{ 
      width: 300px; height: 100px; background: green; float: left; top: 10px; left: 10px; position: absolute; } .b-2{ 
      width: 300px; height: 100px; background: blue; position: absolute; top: 40px; left: 20px; z-index: 100; } .second-item{ 
      background: orange; display: block; top: 30px; left:50px; z-index: 2; } </style> <div class="box"> <div class="first-item total"> <div class="a-1">float绿色</div> <div class="a-2"> <div class="b-2">100蓝色</div> </div> </div> <div class="second-item total">2橙色</div> </div> </body> </html> 

生成的效果如下图,因为first-item 并没有生成新的层叠上下文,所以first-item ,second-item,a-1,a-2,b-2这几个元素都是在同一个层叠上下文中,直接利用七个层叠等级规则判断就好:

请添加图片描述

8.2,多层dom结构,多个层叠上下文层级的情况

给上文的first-item增加一个样式:

.first-item{ 
    z-index: 1; } 

效果变成:

请添加图片描述

这是因为first-item也创建一个层叠上下文,和second-item创建的并列,并且上下文层级低于second-item。于是即使b-2的z-index:100也无法高于second-item。

九,总结

对于z-index的使用规律,MDN实际上就简单一句话:”z-index越大则越上层,有爹则拼爹“。

实际上,则是:

1,同一个层叠上下文中,z-index越大则越上层。 2,不同层级上下文,则层级越高越上层。 3,层级等级和层叠等级相同的,则后来的覆盖之前的。 

其实很多人误解的一点就是以为dom结构和层叠上下文层级并没有严格的映射关系。a元素的n层孙元素,有可能和a是在同一个层叠上下文中的。

到此这篇重新理解z-index的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 查看nginx日志文件2024-11-29 21:45:06
  • nginx的常用记录2024-11-29 21:45:06
  • 自定义柱状图-条状图——不同区间值,显示不同颜色2024-11-29 21:45:06
  • 自定义elementui的前缀2024-11-29 21:45:06
  • flex布局设置一行显示多个,水平布局,自动换行2024-11-29 21:45:06
  • el-table的使用总结2024-11-29 21:45:06
  • 解决谷歌浏览器打开后是毒霸浏览器的问题2024-11-29 21:45:06
  • 使用uni-app创建扫码连接wifi小程序2024-11-29 21:45:06
  • nginx的下载和安装2024-11-29 21:45:06
  • 《第一行代码》 第五章:详解广播机制2024-11-29 21:45:06
  • 全屏图片