目录
前言
最近关于z-index问到了这方面的,只了解值越大,越排在z轴的上面。其实这个问题有很深可以发掘。
注意:
- 首先,
z-index
属性值并不是在任何元素上都有效果。它仅在定位元素(定义了position
属性,且属性值为非static
值的元素)上有效果。- 判断元素在
Z轴
上的堆叠顺序,不仅仅是直接比较两个元素的z-index
值的大小,这个堆叠顺序实际由元素的层叠上下文、层叠等级共同决定。
什么是“层叠上下文”
层叠上下文(stacking context),是HTML中一个三维的概念。每个盒模型的位置是三维的,分别是平面画布上的X轴
,Y轴
以及表示层叠的Z轴
。一般情况下,元素在页面上沿X轴Y轴
平铺,我们察觉不到它们在Z轴
上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖。
如果一个元素含有层叠上下文,(也就是说它是层叠上下文元素),我们可以理解为这个元素在Z轴
上就“高人一等”,最终表现就是它离屏幕观察者更近。
举个例子
1.在一个层叠上下文内
<style>
div {
position: relative;
width: 100px;
height: 100px;
}
p {
position: absolute;
font-size: 20px;
width: 100px;
height: 100px;
}
.a {
background-color: blue;
z-index: 1;
}
.b {
background-color: green;
z-index: 2;
top: 20px;
left: 20px;
}
.c {
background-color: red;
z-index: 3;
top: -20px;
left: 40px;
}
</style>
<body>
<div>
<p class="a">a</p>
<p class="b">b</p>
</div>
<div>
<p class="c">c</p>
</div>
</body>
有两个div,p.a、p.b被包裹在一个div里,p.c被包裹在另一个盒子里,只为.a、.b、.c设置position
和z-index
属性
效果:
因为p.a、p.b、p.c三个的父元素div都没有设置
z-index
,所以不会产生层叠上下文,所以.a、.b、.c都处于由<html></html>
标签产生的“根层叠上下文”中,属于同一个层叠上下文,此时谁的z-index
值大,谁在上面。
2.在多个层叠上下文内
<style>
div {
width: 100px;
height: 100px;
position: relative;
}
.box1 {
z-index: 2;
}
.box2 {
z-index: 1;
}
p {
position: absolute;
font-size: 20px;
width: 100px;
height: 100px;
}
.a {
background-color: blue;
z-index: 100;
}
.b {
background-color: green;
top: 20px;
left: 20px;
z-index: 200;
}
.c {
background-color: red;
top: -20px;
left: 40px;
z-index: 9999;
}
</style>
<body>
<div class="box1">
<p class="a">a</p>
<p class="b">b</p>
</div>
<div class="box2">
<p class="c">c</p>
</div>
</body>
有两个div,p.a、p.b被包裹在一个div里,p.c被包裹在另一个盒子里,同时为两个div和.a、.b、.c设置position
和z-index
属性
效果:
虽然
p.c
元素的z-index
值为9999,远大于p.a
和p.b
的z-index
值,但是由于p.a
、p.b
的父元素div.box1
产生的层叠上下文的z-index
的值为2,p.c
的父元素div.box2
所产生的层叠上下文的z-index
值为1,所以p.c
永远在p.a
和p.b
下面。同时,如果我们只更改
p.a
和p.b
的z-index
值,由于这两个元素都在父元素div.box1
产生的层叠上下文中,所以,谁的z-index
值大,谁在上面。
层叠顺序
为什么
inline/inline-block
元素的层叠顺序要高于block
(块级)/float
(浮动)元素?像border/background
属于装饰元素的属性,浮动和块级元素一般用来页面布局,而网页设计之初最重要的就是文字内容,所以在发生层叠时会优先显示文字内容,保证其不被覆盖。
css样式对层叠上下文的影响
CSS3中出现了很多新属性,其中一些属性对层叠上下文也产生了很大的影响。如下:
- 父元素的display属性值为
flex|inline-flex
,子元素z-index
属性值不为auto
的时候,子元素为层叠上下文元素; - 元素的
opacity
属性值不是1
; - 元素的
transform
属性值不是none
; - 元素的
filter
属性值不是none
;
<style>
.box {
display: flex;
}
.parent {
width: 200px;
height: 100px;
background: #168bf5;
/* 虽然设置了z-index,但是没有设置position,z-index无效,.parent还是普通元素,没有产生层叠上下文 */
z-index: 1;
}
.child {
width: 100px;
height: 200px;
background: #32d19c;
position: relative;
z-index: -1;
}
</style>
</head>
<body>
<div class="box">
<div class="parent"> parent</div>
<div class="child">child</div>
</div>
</div>
</body>
由于给父元素添加了display:flex,所以子元素产生了层叠上下文,又因为parent的背景的层叠顺序比child的z-index:-1的层叠顺序低,所以child展示在上面,
如果没有display:flex,我们发现parent没有设置position,所以z-index无效,且child的z-index设置为-1,所以parent展示在上面
总结
1、首先先看要比较的两个元素是否处于同一个层叠上下文中
1.1如果是,谁的层叠等级大,谁在上面(怎么判断层叠等级大小呢?——看“层叠顺序”图)。 1.2如果两个元素不在统一层叠上下文中,请先比较他们所处的层叠上下文的层叠等级。
2、当两个元素层叠等级相同、层叠顺序相同时,在DOM结构中后面的元素层叠等级在前面元素之上。
参考文章: