css--深入由z-index引发的层叠上下文、层叠等级和层叠顺序的思考
前言
在编写css样式代码的时候,我们经常会遇到z-index属性的使用,我们可能只了解z-index能够提高元素的层级,并不知道具体是怎么实现的。本文就来总结一个由z-index 引发的层叠上下文和层叠顺序相关知识点,有了这方面的了解,才能减少开发中遇到的bug,同时这也是面试中经常遇到的问题。
正文
1、z-index 属性
通常情况下,html 页面被认为是二维的,相当于只有 x 和 y 轴,因为文本、图像和其他元素被排列在页面上而不重叠。这种情况下只有一个渲染进程,所有元素都知道其他元素所占用的空间。z-index 属性可让你在渲染内容时调整对象分层的顺序。z-index
属性设定了一个定位元素及其后代元素或 flex 项目的 z-order。 当元素之间重叠的时候, z-index 较大的元素会覆盖较小的元素在上层进行显示。这样似的html页面变成了一个三维的空间。
根据上面的理解,我们不难实现如下的效果:
代码段1如下:我们只需要改变box盒子的z-index值的大小就会改变盒子的层叠顺序。
<style> div { width: 100px; height: 100px; font-size: 14px; } .box1 { position: absolute; top: 20px; left: 20px; background-color: red; } .box2 { position: absolute; top: 40px; left: 40px; background-color: yellow; } .box3 { position: absolute; top: 60px; left: 60px; background-color: green; } </style> <body> <div class="box1">box1</div> <div class="box2">box2</div> <div class="box3">box3</div> </body>
初次看上面的代码,会发现 z-index 值越大在z轴上就越靠上,离浏览器屏幕越近。但是仔细思考,你会发现这里存在很多疑惑:z-index是在任何元素上面都有效果吗?难道z-index的值的大小直接影响到元素的层叠顺序吗?
我们再来看下下面的代码段2:
<style> .box1,.box2 { width: 100px; height: 100px; font-size: 14px; display: flex; } .box1 { position: absolute; top: 20px; left: 20px; background-color: red; z-index: 1; } .box2 { position: absolute; top: 40px; left: 40px; background-color: yellow; } .box1-item1 { width: 50px; height: 100px; border: 1px solid black; } .box1-item2 { width: 50px; height: 100px; border: 1px solid blue; } .box2-item1 { width: 50px; height: 100px; border: 1px solid black; z-index: 10; } .box2-item2 { width: 50px; height: 100px; border: 1px solid blue; z-index: 10; } </style> <body> <div class="box1"> <div class="box1-item1">1</div> <div class="box1-item2">2</div> </div> <div class="box2"> <div class="box2-item1">1</div> <div class="box2-item2">2</div> </div> </body>
效果如下:
产生这样的效果,究竟是为什么呢,明明box2-item1、box2-item2 的z-index属性值更大,结果这两个盒子会被覆盖了呢。要想彻底知道其中的缘由,我们需要知道层叠上下、层叠等级、层叠顺序这几个概念。
2、层叠上下文
层叠上下文(Stacking context),是html页面中的一个三维的概念,就是上面提到的 z-index 的产生,导致页面有了z轴。默认a-index值为 aotu ,即z轴的0点处,同时可以设置z-index为正值和负值,表示该层叠上下文元素在z轴距离屏幕的远近。
3、层叠等级
层叠等级(stacking level),在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在Z轴
上的上下顺序。在其他普通元素中,它描述定义的是这些普通元素在Z轴
上的上下顺序。只有在同一层叠上下文中,层叠等级才有意义,z-index优先级最高。产生层叠上下文的条件:
-
文档根元素(
<html>
); -
position
值为absolute
(绝对定位)或relative
(相对定位)且z-index
值不为auto
的元素; -
position
值为fixed
(固定定位)或sticky
(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持); -
flex (
flexbox
(en-US)) 容器的子元素,且z-index
值不为auto
; -
grid (
grid
) 容器的子元素,且z-index
值不为auto
; -
opacity
属性值小于1
的元素(参见 the specification for opacity); -
mix-blend-mode
属性值不为normal
的元素; -
以下任意属性值不为
none
的元素:isolation
属性值为isolate
的元素;isolation
属性值为isolate
的元素;isolation属性值为isolate的元素transform
filter
perspective
clip-path
mask
/mask-image
/mask-border
-
-webkit-overflow-scrolling
属性值为touch
的元素; - isolation 属性值为 isolate 的元素;
-
will-change
值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素(参考这篇文章); -
contain
属性值为layout
、paint
或包含它们其中之一的合成值(比如contain: strict
、contain: content
)的元素。
在层叠上下文中,子元素同样也按照上面解释的规则进行层叠。 重要的是,其子级层叠上下文的 z-index
值只在父级中才有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元。
总结:
- 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。
- 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
- 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。
4、层叠顺序
层叠顺序”(stacking order)表示元素发生层叠时按照特定的顺序规则在Z轴
上垂直显示。由此可见,前面所说的“层叠上下文”和“层叠等级”是一种概念,而这里的“层叠顺序”是一种规则。
5、分析代码段2
代码段2中,因为box1 和 box2 盒子都设置了position :absolute,并且box1设置了z-index:1,使得根层级上下文中 box1层级等级高于box2,因此产生了下图中左图的效果。在box1 盒子中设置flex,而两个子盒子box1-item1和box1-item2 默认的z-index值为auto,不会产生层级上下文关系,因此产生了下图中中间的效果图。在box2中设置了flex属性,而里面的 box2-item1 和 box2-item2 都设置了z-index值为10,产生了层级上下文,会高于box2 的Background 顺序显示,因此产生了下图中有图的效果。
写在最后
以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长之路会持续更新一些工作中常见的问题和技术点。