深入理解CSS中的z-index
深入理解z-index
在MDN上的定义是z-index
属性设定了一个定位元素及其后代元素或 flex 项目的 z-order。 当元素之间重叠的时候, z-index 较大的元素会覆盖较小的元素在上层进行显示。
但是这个说明太含糊了,当遇到z-index
不生效的情况时,就不知所以然了,最近也查看了很多和z-index
相关的资料,决定把z-index
相关知识系统性的梳理一遍.
以前我总是很片面的认为元素在Z轴上的层叠顺序只跟z-index
值的大小有关, 属性值大的元素显示在上面、属性值小的元素显示在下面,但是就像下面, 为啥z-index
不生效呢,明明box1的z-index
属性值大于box2的.
事实上
z-index
属性并非对所有元素都生效, 它仅对定位元素生效而且定位元素的prosition
属性值不为static
时才会起作用:其实判断元素在Z轴的层叠顺序取决于两个方面: 元素所在的层叠上下文、元素自身的层叠级别, 在此之前我们先了解一下这两个概念:
z-index
通常情况下,html
页面可以被认为是二维的,因为文本,图像和其他元素被排列在页面上而不重叠。在这种情况下,只有一个渲染进程,所有元素都知道其他元素所占用的空间。
在 CSS 2.1
中, 所有的盒模型元素都处于三维坐标系中。 除了我们常用的横坐标和纵坐标, 盒模型元素还可以沿着“z
轴”层叠摆放, 当他们相互覆盖时,z
轴顺序就变得十分重要。这意味着 CSS
允许你在现有的渲染引擎上层叠的摆放盒模型元素。 所有的层都可以用一个整数( z 轴顺序)来表明当前层在 z 轴的位置。 数字越大, 元素越接近观察者。Z 轴顺序用 CSS 的 z-index
属性来指定。z-index
的属性值默认为auto,可设置值为一个整数、可为正整数也可以是负整数
层叠上下文
MDN上的定义: 我们假定用户正面向(浏览器)视窗或网页,而 HTML
元素沿着其相对于用户的一条虚构的z
轴排开,层叠上下文就是对这些HTML
元素的一个三维构想。众HTML
元素基于其元素属性按照优先级顺序占据这个空间。
那么如何才能创建层叠上下文呢?我在网上看到过一个, 总结的很好: 目前有三类方法创建层叠上下文
- 元素自身就能创建的
- 需要结合
z-index
才能创建的 - 不需要
z-index
就能创建的
一、元素自身形成层叠上下文
文档根元素(<html>
)会自动形成一个层叠上下文, 不需要结合任何其他属性
二、需要配合z-index才能触发创建层叠上下文的
position
值为 absolute
(绝对定位)或 relative
(相对定位)且 z-index
属性值不为 auto
的元素;
采用flex
布局容器的子元素, 且子元素 z-index
属性值不为 auto
的元素;
三、不要配合z-index就能触发创建层叠上下文的
position
值为 fixed
(固定定位)或 sticky
(粘滞定位)的元素;
透明度opacity
属性值不为1
的元素
转换transform
属性值不为none
的元素
滤镜filter
属性值不为none
的元素
上面列举出来的都是一些常用到的属性,当然还有其他的属性值设置也能触发形成层叠上下文,这里就不一一列举了,有兴趣的同学可以去MDN文档查看.这里我们需要注意的几点:
- 层叠上下文可以包含在其他层叠上下文中, 由于根元素
HTML
本身就是一个层叠上下文,所以页面文档中的创建的层叠上下文都是HTML
元素层级的一个子级 - 当某个元素创建了层叠上下文后, 应当把它及其后代当成一个整体,去判断层叠顺序
- 父子元素、兄弟元素都可能会处于同一层叠上下文中
层叠级别
在不考虑层叠上下文的情况下, 元素的层叠级别就是判断发生层叠时,元素在Z轴如何显示的依据, 下图就是著名的7阶层叠水平:
background/border
、负z-index
元素、块级元素、浮动元素、行内/行内块元素、z-index
为0元素、正z-index
元素.
文本节点我们也看成是一个行内元素
判断层叠顺序
在理解了层叠上下文和元素层叠水平的概念后,现在我们就可以说说元素在Z轴上的层叠顺序到底是怎么回事了: 元素在Z轴上的层叠顺序取决于两个方面: 元素所在的层叠上下文、元素自身的层叠级别,如果抛开层叠上下文来判断元素在Z
轴上的层叠顺序就是瞎胡闹
1. 当要比较的两个元素在同一层叠上下文时, 就按照元素自身的层叠级别, 如果级别相同时后则覆盖前者
同一层叠上下文中的兄弟元素
html
元素形成的上下文) ,二者都是行内块元素,级别相同, 所以后者覆盖前者上图box1、box2也都处在同一层叠上下文中(
htm
l元素形成的上下文),但box1是行内元素,box2是块级元素, 根据元素的层叠级别,行内元素要高于块级元素, 所以box1显示在box2上面; 但是有个奇怪的现象, box1只能覆盖box2的背景,却不能覆盖box2内的字体.......为啥呢? 其实这个现象我们在上面也有提到过: 文本节点我们也看成是一个行内元素, 由于行内元素的级别要高于background/border
,所以box1不能覆盖box2元素内的文本节点.同一层叠上下文中的父子元素
也有可能是父子元素会出现在同一层叠上下文中, 其实刚刚上面我们说的字体的例子,就可以看成是父子元素在同一层叠上下文中, 这里就不在另外举例啦
2. 当要比较的两个元素不在同一层叠上下文时, 需要先向上查找到两者所在的共同的且最近的层叠上下文,然后在根据第1条规则来判断
链接:https://juejin.cn/post/6967737753983254564