CSS中的层叠上下文和层叠顺序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSS中的层叠上下文和层叠顺序相关的知识,希望对你有一定的参考价值。
copy @ from http://www.zhangxinxu.com
四、务必牢记的层叠准则
下面这两个是层叠领域的黄金准则。当元素发生层叠的时候,其覆盖关系遵循下面2个准则:
- 谁大谁上:当具有明显的层叠水平标示的时候,如识别的z-indx值,在同一个层叠上下文领域,层叠水平值大的那一个覆盖小的那一个。通俗讲就是官大的压死官小的。
- 后来居上:当元素的层叠水平一致、层叠顺序相同的时候,在DOM流中处于后面的元素会覆盖前面的元素。
在CSS和html领域,只要元素发生了重叠,都离不开上面这两个黄金准则。因为后面会有多个实例说明,这里就到此为止。
五、层叠上下文的特性
层叠上下文元素有如下特性:
- 层叠上下文的层叠水平要比普通元素高(原因后面会说明);
- 层叠上下文可以阻断元素的混合模式(见此文第二部分说明);
- 层叠上下文可以嵌套,内部层叠上下文及其所有子元素均受制于外部的层叠上下文。
- 每个层叠上下文和兄弟元素独立,也就是当进行层叠变化或渲染的时候,只需要考虑后代元素。
- 每个层叠上下文是自成体系的,当元素发生层叠的时候,整个元素被认为是在父层叠上下文的层叠顺序中。
- 觉得多数常见,z-index根本就没有出现的必要。知道了内联元素的层叠水平比块状元素高,于是,某条线你想覆盖上去的时候,需要设置
position:relative
吗?不需要,inline-block
化就可以。因为IE6/IE7position:relative
会创建层叠上下文,很烦的 -
③. CSS3与新时代的层叠上下文
CSS3的出现除了带来了新属性,同时还对过去的很多规则发出了挑战。例如,CSS3transform
对overflow隐藏对position:fixed定位的影响等。而这里,层叠上下文这一块的影响要更加广泛与显著。如下:
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
.
基本上每一项都有很多槽点。
1. display:flex|inline-flex与层叠上下文
注意,这里的规则有些负责复杂。要满足两个条件才能形成层叠上下文:条件1是父级需要是display:flex
或者display:inline-flex
水平,条件2是子元素的z-index不是auto
,必须是数值。此时,这个子元素为层叠上下文元素,没错,注意了,是子元素,不是flex父级元素。眼见为实,给大家上例子吧。
如下HTML和CSS代码:
<div class="box"> <div> <img src="mm1.jpg"> </div> </div>
.box { } .box > div { background-color: blue; z-index: 1; } /* 此时该div是普通元素,z-index无效 */ .box > div > img { position: relative; z-index: -1; right: -150px; /* 注意这里是负值z-index */ }
结果如下:
会发现,妹子跑到蓝色背景的下面了。为什么呢?层叠顺序图可以找到答案,如下:
从上图可以看出负值z-index的层叠顺序在block水平元素的下面,而蓝色背景
div
元素是个普通元素,因此,妹子直接穿越过去,在蓝色背景后面的显示了。现在,我们CSS微调下,增加
display:flex
, 如下:.box { display: flex; } .box > div { background-color: blue; z-index: 1; } /* 此时该div是层叠上下文元素,同时z-index生效 */ .box > div > img { position: relative; z-index: -1; right: -150px; /* 注意这里是负值z-index */ }
结果:
会发现,妹子在蓝色背景上面显示了,为什么呢?层叠顺序图可以找到答案,如下:
从上图可以看出负值
z-index
的层叠顺序在当前第一个父层叠上下文元素的上面,而此时,那个z-index
值为1
的蓝色背景<div>
的父元素的display
值是flex
,一下子升官发财变成层叠上下文元素了,于是,图片在蓝色背景上面显示了。这个现象也证实了层叠上下文元素是flex
子元素,而不是flex
容器元素。另外,另外,这个例子也颠覆了我们传统的对
z-index
的理解。在CSS2.1时代,z-index
属性必须和定位元素一起使用才有作用,但是,在CSS3的世界里,非定位元素也能和z-index
愉快地搞基。2. opacity与层叠上下文
我们直接看代码,原理和上面例子一样,就不解释了。如下HTML和CSS代码:
<div class="box"> <img src="mm1.jpg"> </div>
.box { background-color: blue; } .box > img { position: relative; z-index: -1; right: -150px; }
结果如下:
然后价格透明度,例如50%透明:
.box { background-color: blue; opacity: 0.5; } .box > img { position: relative; z-index: -1; right: -150px; }
结果如下:
原因就是半透明元素具有层叠上下文,妹子图片的
z-index:-1
无法穿透,于是,在蓝色背景上面乖乖显示了。3. transform与层叠上下文
应用了transform变换的元素同样具有菜单上下文。我们直接看应用后的结果,如下CSS代码:
.box { background-color: blue; transform: rotate(15deg); } .box > img { position: relative; z-index: -1; right: -150px; }
结果如下:
妹子同样在蓝色背景之上。
4. mix-blend-mode与层叠上下文
mix-blend-mode
类似于PS中的混合模式,之前专门有文章介绍-“CSS3混合模式mix-blend-mode简介”。元素和白色背景混合。无论哪种模式,要么全白,要么没有任何变化。为了让大家有直观感受,因此,下面例子我特意加了个原创平铺背景:
.box { background-color: blue; mix-blend-mode: darken; } .box > img { position: relative; z-index: -1; right: -150px; }
结果如下:
需要注意的是,目前,IE浏览器(包括IE14)还不支持
mix-blend-mode
,因此,要想看到妹子在背景色之上,请使用Chrome或FireFox。同样的,因为蓝色背景元素升级成了层叠上下文,因此,
z-index:-1
无法穿透,在蓝色背景上显示了。5. filter与层叠上下文
此处说的filter
是CSS3中规范的滤镜,不是旧IE时代私有的那些,虽然目的类似。同样的,我之前有提过,例如图片的灰度或者图片的毛玻璃效果等。我们使用常见的模糊效果示意下:
.box { background-color: blue; filter: blur(5px); } .box > img { position: relative; z-index: -1; right: -150px; }
结果如下:
好吧,果然被你猜对了,妹子蓝色床上躺着,只是你眼镜摘了,看得有些不够真切罢了。
6. isolation:isolate与层叠上下文
isolation:isolate
这个声明是mix-blend-mode
应运而生的。默认情况下,mix-blend-mode
会混合z轴所有层叠在下面的元素,要是我们不希望某个层叠的元素参与混合怎么办呢?就是使用isolation:isolate
。由于一言难尽,我特意为此写了篇文章:“理解CSS3 isolation: isolate的表现和作用”,解释了其阻隔混合模式的原理,建议大家看下。要演示这个效果,我需要重新设计下,如下HTML结构:
<img src="img/mm2.jpg" class="mode"> <div class="box"> <img src="mm1.jpg"> </div>
CSS主要代码如下:
.mode { /* 竖妹子绝对定位,同时混合模式 */ position: absolute; mix-blend-mode: darken; } .box { background: blue; } .box > img { position: relative; z-index: -1; }
结构如下:
会发现,横妹子被混合模式了。此时,我们给妹子所在容器增加
isolation:isolate
,如下CSS所示:.mode { /* 竖妹子绝对定位,同时混合模式 */ position: absolute; mix-blend-mode: darken; } .box { background: blue; isolation:isolate; } .box > img { position: relative; z-index: -1; }
结果为:
会发现横着的妹子跑到蓝色背景上面了。这表明确实创建了层叠上下文。
7. will-change与层叠上下文
关于will-change
,如果有同学还不了解,可以参见我之前写的文章:“使用CSS3 will-change提高页面滚动、动画等渲染性能”。都是类似的演示代码:
.box { background-color: blue; will-change: transform; } .box > img { position: relative; z-index: -1; right: -150px; }
结果如下:
果然不出所料,妹子上了蓝色的背景。
七、层叠上下文与层叠顺序
本文多次提到,一旦普通元素具有了层叠上下文,其层叠顺序就会变高。那它的层叠顺序究竟在哪个位置呢?
这里需要分两种情况讨论:
- 如果层叠上下文元素不依赖
z-index
数值,则其层叠顺序是z-index:auto
可看成z:index:0
级别; - 如果层叠上下文元素依赖
z-index
数值,则其层叠顺序由z-index
值决定。
于是乎,我们上面提供的层叠顺序表,实际上还是缺少其他重要信息。我又花功夫重新绘制了一个更完整的7阶层叠顺序图(同样的版权所有,商业请购买,可得无水印大图):
大家知道为什么定位元素会层叠在普通元素的上面吗?
其根本原因就在于,元素一旦成为定位元素,其
z-index
就会自动生效,此时其z-index
就是默认的auto
,也就是0
级别,根据上面的层叠顺序表,就会覆盖inline
或block
或float
元素。而不支持z-index的层叠上下文元素天然
z-index:auto
级别,也就意味着,层叠上下文元素和定位元素是一个层叠顺序的,于是当他们发生层叠的时候,遵循的是“后来居上”准则。我们可以速度测试下:
<img src="mm1" style="position:relative"> <img src="mm2" style="transform:scale(1);">
<img src="mm2" style="transform:scale(1);"> <img src="mm1" style="position:relative">
会发现,两者样式一模一样,仅仅是在DOM流中的位置不一样,导致他们的层叠表现不一样,后面的妹子趴在了前面妹子的身上。这也说明了,层叠上下文元素的层叠顺序就是
z-index:auto
级别。z-index值与层叠顺序
如果元素支持z-index值,则层叠顺序就要好理解些了,比较数值大小嘛,小盆友都会,本质上是应用的“谁大谁上”的准则。在以前,我们只需要关心定位元素的z-index就好,但是,在CSS3时代,flex子项也支持z-index
,使得我们面对的情况比以前要负复杂。然而,好的是,规则都是一样的,对于z-index
的使用和表现也是如此,套用上面的7阶层叠顺序表就可以了。同样,举个简单例子,看下
z-index:-1
和z-index:1
变化对层叠表现的影响,如下两段HTML:<div style="display:flex; background:blue;"> <img src="mm1.jpg" style="z-index:-1;"> </div>
<div style="display:flex; background:blue;"> <img src="mm1.jpg" style="z-index:1;"> </div>
最后,会发现,
z-index:-1
跑到了背景色小面,而z-index:1
高高在上。一个与层叠上下文相关的有趣的显示现象
在实际项目中,我们可能会渐进使用CSS3的fadeIn淡入animation效果增强体验,于是,我们可能就会遇到类似下面的现象:您可以狠狠地点击这里:CSS3 fadeIn淡入animation动画有趣现象
有一个绝对定位的黑色半透明层覆盖在图片上,默认显示是这样的:
但是,一旦图片开始走fadeIn淡出的CSS3动画,文字跑到图片后面去了:
为什么会这样?
实际上,学了本文的内容,就很简单了!fadeIn动画本质是
opacity
透明度的变化:@keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } }
要知道,
opacity
的值不是1
的时候,是具有层叠上下文的,层叠顺序是z-index:auto
级别,跟没有z-index
值的absolute
绝对定位元素是平起平坐的。而本demo中的文字元素在图片元素的前面,于是,当CSS3动画只要不是最终一瞬间的opacity: 1
,位于DOM流后面的图片就会遵循“后来居上”准则,覆盖文字。这就是原因,于是,我们想要解决这个问题就很简单。
1. 调整DOM流的先后顺序;
2. 提高文字的层叠顺序,例如,设置z-index:1
;
以上是关于CSS中的层叠上下文和层叠顺序的主要内容,如果未能解决你的问题,请参考以下文章