层叠上下文
关于 z-index
z-index
这个属性并不是在任何元素上都具有效果,只有其定位样式属性 position
不等于 static
时,才会生效。
另外,判断一个元素在 z 轴上的 堆叠顺序,不仅仅是比较元素的 z-index
值大小,这个 堆叠顺序 实际上由 层叠上下文 和 层叠等级 共同决定。
层叠等级
层叠等级英文称作 "stacking level",其决定了同一个层叠上下文中元素在 z 轴上的 堆叠顺序。在同一个层叠上下文中,内部子元素的层叠顺序可以参考下面的规则。
- 层叠上下文容器的
background/border
是处于最低层叠顺序 - 其次是
z-index < 0
的子元素 - 如果
z-index
缺省或者显示定义为z-index:0 | auto
或者z-index
取值相同,那么有block < float < inline-block = inline
- 最后是
z-index
谁大谁就处于上方
下面这两个是层叠领域的黄金准则。当元素发生层叠的时候,其覆盖关系遵循下面 3 个准则:
- 谁大谁上:当具有明显的层叠等级标示的时候,如识别的 z-indx 值,在同一个层叠上下文领域,层叠等级值大的那一个覆盖小的那一个
- 后来居上:当元素的 层叠等级一致、层叠顺序相同 的时候,在 DOM流 中处于后面的元素会覆盖前面的元素
- 如果
z-index
缺省或者显示定义为z-index:0 | auto
或者z-index
取值相同,那么有block < float < inline-block = inline
你需要的 "套路"
上面说了这么多,可能你还是有点懵,下面梳理一下当遇到元素层叠时,我们怎么能很清晰地判断出他们谁在上谁在下。
- 首先比较两个元素是否位于同一个层叠上下文中
- 如果在同一个层叠上下文,那么根据上面的准则来比较
- 如果不在同一个层叠上下文,那么它们的层叠顺序 取决于位于同一个层叠上下文的祖先元素的层叠顺序 决定
- 当两个元素层叠等级相同、层叠顺序相同时,在 DOM 结构中后面的元素层叠等级在前面元素之上
层叠上下文
层叠上下文和块级格式上下文(BFC)类似,都具有上下文这个概念,通俗来讲就是具有某种特性或者规则的 "作用域"。
层叠上下文是由具有特定 CSS 属性的元素创建的,它的作用就是决定该元素及其内部
层叠上下文的创建
<html>
根元素本身具有一个根层叠上下文- 普通元素设置
position
属性为非static
并设置z-index
属性为 具体数值(不能是 auto),产生层叠上下文 - CSS3 中的某些属性也会产生层叠上下文(详见后文)
层叠上下文的例子
div#1
、div#2
和div#3
是处于同一个根元素的层叠上下文中的div#4
、div#5
和div#6
是处于div#3
创建的层叠上下文中的
div#1
和 div#3
处于同一个层叠上下文中,此时直接比较它们层叠顺序,z-index: 5
大于 z-index: 4
,所以 div#1
是位于 div#3
上方的。
而 div#1
和 div#4
位于不同的层叠上下文,但是 div#1
和 div#4
的父元素是处于同一个层叠上下文中,并且 div#1
的层叠顺序是大于 div#4
的父元素的层叠顺序,因此就算 div#4
的 z-index
大于 div#1
的 z-index
,div#4
依旧位于其下方。
下面继续来看一个例子。
<div style="position:relative; z-index:auto;">
<img src="mm1.jpg" style="position:absolute; z-index:2;">
</div>
<div style="position:relative; z-index:auto;">
<img src="mm2.jpg" style="position:relative; z-index:1;">
</div>
图片1 和图片 2 的父元素都不会产生新的层叠上下文,因为它们的 z-index
取值为 auto
,所以两张图片是位于同一个根层叠上下文中的,前者的 z-index
大于后者,所以图片1 位于图片 2 上方。
下面将这两个图片的父元素修改一下,让其能够产生层叠顺序相同的层叠上下文。
<div style="position:relative; z-index:0;">
<img src="mm1.jpg" style="position:absolute; z-index:2;">
</div>
<div style="position:relative; z-index:0;">
<img src="mm2.jpg" style="position:relative; z-index:1;">
</div>
由于这两张图片不位于同一个层叠上下文,所以它们的 层叠顺序取决于位于同一个层叠上下文的父元素的层叠顺序,这两个父元素层叠顺序相同,所以在 DOM 树考后的那个父元素会位于前面那个父元素上方,此时图片 2 就位于 图片 1 上方了。
CSS3 属性对层叠上下文的影响
CSS3的出现除了带来了新属性,同时还对过去的很多规则发出了挑战,特别是层叠上下文这一块的影响要更加广泛与显著。
如下:
z-index
值不为auto
的flex
项(父元素display: flex | inline-flex
)- 元素的
opacity
值不是1
- 元素的
transform
值不是none
- 元素
mix-blend-mode
值不是normal
- 元素的
filter
值不是none
- 元素的
isolation
值是isolate
will-change
指定的属性值为上面任意一个- 元素的
-webkit-overflow-scrolling
设为touch
下面会挑几个常用的来讲。
弹性布局与层叠上下文
对于弹性合作的子项,其 z-index
只要是数值(不需要 position
),就会产生新的层叠上下文。
transform、opacity 和 will-change 与层叠上下文
transform
、opacity
和 will-change
只要不是默认值,那么该元素就会产生新的层叠上下文。
层叠上下文对鼠标事件的影响
pointer-events: none 可以无视