文档章节

深入理解CSS中的层叠上下文和层叠顺序

L
 LorinLuo
发布于 2016/03/03 11:43
字数 4137
阅读 58
收藏 1

深入理解CSS中的层叠上下文和层叠顺序

上下文

前端大全 · 2016-01-20 20:12

深入理解CSS中的层叠上下文和层叠顺序

(点击上方,可快速关注)


作者:张鑫旭

网址:http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/

零、世间的道理都是想通的


在这个世界上,凡事都有个先后顺序,凡物都有个论资排辈。比方说食堂排队打饭,对吧,讲求先到先得,总不可能一拥而上。再比如说话语权,老婆的话永远是对的,领导的话永远是对的。


在CSS届,也是如此。只是,一般情况下,大家歌舞升平,看不出什么差异,即所谓的众生平等。但是,当发生冲突发生纠葛的时候,显然,是不可能做到完全等同的,先后顺序,身份差异就显现出来了。例如,杰克和罗斯,只能一人浮在木板上,此时,出现了冲突,结果大家都知道的。那对于CSS世界中的元素而言,所谓的“冲突”指什么呢,其中,很重要的一个层面就是“层叠显示冲突”。


默认情况下,网页内容是没有偏移角的垂直视觉呈现,当内容发生层叠的时候,一定会有一个前后的层叠顺序产生,有点类似于真实世界中论资排辈的感觉。


而要理解网页中元素是如何“论资排辈”的,就需要深入理解CSS中的层叠上下文和层叠顺序。


我们大家可能都熟悉CSS中的z-index属性,需要跟大家讲的是,z-index实际上只是CSS层叠上下文和层叠顺序中的一叶小舟。


一、什么是层叠上下文


层叠上下文,英文称作”stacking context”. 是HTML中的一个三维的概念。如果一个元素含有层叠上下文,我们可以理解为这个元素在z轴上就“高人一等”。


这里出现了一个名词-z轴,指的是什么呢?


表示的是用户与屏幕的这条看不见的垂直线(参见下图示意-红线):



层叠上下文是一个概念,跟「块状格式化上下文(BFC)」类似。然而,概念这个东西是比较虚比较抽象的,要想轻松理解,我们需要将其具象化。


怎么个具象化法呢?


你可以把「层叠上下文」理解为当官:网页中有很多很多的元素,我们可以看成是真实世界的芸芸众生。真实世界里,我们大多数人是普通老百姓们,还有一部分人是做官的官员。OK,这里的“官员”就可以理解为网页中的层叠上下文元素。


换句话说,页面中的元素有了层叠上下文,就好比我们普通老百姓当了官,一旦当了官,相比普通老百姓而言,离皇帝更近了,对不对,就等同于网页中元素级别更高,离我们用户更近了。


二、什么是层叠水平


再来说说层叠水平。“层叠水平”英文称作”stacking level”,决定了同一个层叠上下文中元素在z轴上的显示顺序。level这个词很容易让我们联想到我们真正世界中的三六九等、论资排辈。真实世界中,每个人都是独立的个体,包括同卵双胞胎,有差异就有区分。例如,双胞胎虽然长得像Ctrl+C/Ctrl+V得到的,但实际上,出生时间还是有先后顺序的,先出生的那个就大,大哥或大姐。网页中的元素也是如此,页面中的每个元素都是独立的个体,他们一定是会有一个类似的排名排序的情况存在。而这个排名排序、论资排辈就是我们这里所说的“层叠水平”。层叠上下文元素的层叠水平可以理解为官员的职级,1品2品,县长省长之类;对于普通元素,这个嘛……你自己随意理解。


于是,显而易见,所有的元素都有层叠水平,包括层叠上下文元素,层叠上下文元素的层叠水平可以理解为官员的职级,1品2品,县长省长之类。然后,对于普通元素的层叠水平,我们的探讨仅仅局限在当前层叠上下文元素中。为什么呢?因为否则没有意义。


这么理解吧~ 上面提过元素具有层叠上下文好比当官,大家都知道的,这当官的家里都有丫鬟啊保镖啊管家啊什么的。所谓打狗看主人,A官员家里的管家和B官员家里的管家做PK实际上是没有意义的,因为他们牛不牛逼完全由他们的主子决定的。一人得道鸡犬升天,你说这和珅家里的管家和七侠镇娄知县县令家里的管家有可比性吗?李总理的秘书是不是分分钟灭了你村支部书记的秘书(如果有)。


翻译成术语就是:普通元素的层叠水平优先由层叠上下文决定,因此,层叠水平的比较只有在当前层叠上下文元素中才有意义。


需要注意的是,诸位千万不要把层叠水平和CSS的z-index属性混为一谈。没错,某些情况下z-index确实可以影响层叠水平,但是,只限于定位元素以及flex盒子的孩子元素;而层叠水平所有的元素都存在。


三、什么是层叠顺序


再来说说层叠顺序。“层叠顺序”英文称作”stacking order”. 表示元素发生层叠时候有着特定的垂直显示顺序,注意,这里跟上面两个不一样,上面的层叠上下文和层叠水平是概念,而这里的层叠顺序是规则。


在CSS2.1的年代,在CSS3还没有出现的时候(注意这里的前提),层叠顺序规则遵循下面这张图:



有人可能有见过类似图,那个图是很多很多年前老外绘制的,英文内容。而是更关键的是国内估计没有同行进行过验证与实践,实际上很多关键信息缺失。上面是我自己手动重绘的中文版同时补充很多其他地方绝对没有的重要知识信息。如果想要无水印高清大图,点击这里购买(0.5元)。


缺失的关键信息包括:


  1. 位于最低水平的border/background指的是层叠上下文元素的边框和背景色。每一个层叠顺序规则适用于一个完整的层叠上下文元素。

  2. 原图没有呈现inline-block的层叠顺序,实际上,inline-block和inline水平元素是同等level级别。

  3. z-index:0实际上和z-index:auto单纯从层叠水平上看,是可以看成是一样的。注意这里的措辞——“单纯从层叠水平上看”,实际上,两者在层叠上下文领域有着根本性的差异。


下面我要向大家发问了,大家有没有想过,为什么内联元素的层叠顺序要比浮动元素和块状元素都高?


为什么呢?我明明感觉浮动元素和块状元素要更屌一点啊。


嘿嘿嘿,我就不卖关子了,直接看下图的标注说明:



诸如border/background一般为装饰属性,而浮动和块状元素一般用作布局,而内联元素都是内容。网页中最重要的是什么?当然是内容了哈,对不对!


因此,一定要让内容的层叠顺序相当高,当发生层叠是很好,重要的文字啊图片内容可以优先暴露在屏幕上。例如,文字和浮动图片重叠的时候:



上面说的这些层叠顺序规则还是老时代的,如果把CSS3也牵扯进来,科科,事情就不一样了。


四、务必牢记的层叠准则


下面这两个是层叠领域的黄金准则。当元素发生层叠的时候,其覆盖关系遵循下面2个准则:


  1. 谁大谁上:当具有明显的层叠水平标示的时候,如识别的z-indx值,在同一个层叠上下文领域,层叠水平值大的那一个覆盖小的那一个。通俗讲就是官大的压死官小的。

  2. 后来居上:当元素的层叠水平一致、层叠顺序相同的时候,在DOM流中处于后面的元素会覆盖前面的元素。


在CSS和HTML领域,只要元素发生了重叠,都离不开上面这两个黄金准则。因为后面会有多个实例说明,这里就到此为止。


五、层叠上下文的特性


层叠上下文元素有如下特性:


  • 层叠上下文的层叠水平要比普通元素高(原因后面会说明);

  • 层叠上下文可以阻断元素的混合模式(见此文第二部分说明);

  • 层叠上下文可以嵌套,内部层叠上下文及其所有子元素均受制于外部的层叠上下文。

  • 每个层叠上下文和兄弟元素独立,也就是当进行层叠变化或渲染的时候,只需要考虑后代元素。

  • 每个层叠上下文是自成体系的,当元素发生层叠的时候,整个元素被认为是在父层叠上下文的层叠顺序中。


翻译成真实世界语言就是:


  • 当官的比老百姓更有机会面见圣上;

  • 领导下去考察,会被当地官员阻隔只看到繁荣看不到真实民情;

  • 一个家里,爸爸可以当官,孩子也是可以同时当官的。但是,孩子这个官要受爸爸控制。

  • 自己当官,兄弟不占光。有什么福利或者变故只会影响自己的孩子们。

  • 每个当官的都有属于自己的小团体,当家眷管家发生摩擦磕碰的时候(包括和其他官员的家眷管家),都是要优先看当官的也就是主子的脸色。


六、层叠上下文的创建


卖了这么多文字,到底层叠上下文是个什么鬼,倒是拿出来瞅瞅啊!


哈哈。如同块状格式化上下文,层叠上下文也基本上是有一些特定的CSS属性创建的。我将其总结为3个流派,也就是做官的3种途径:


  1. 皇亲国戚派:页面根元素天生具有层叠上下文,称之为“根层叠上下文”。

  2. 科考入选派:z-index值为数值的定位元素的传统层叠上下文。

  3. 其他当官途径:其他CSS3属性。


//zxx: 下面很多例子是实时CSS效果,建议您去原地址浏览,以便预览更准确的效果。


①. 根层叠上下文


指的是页面根元素,也就是滚动条的默认的始作俑者<html>元素。这就是为什么,绝对定位元素在left/top等值定位的时候,如果没有其他定位元素限制,会相对浏览器窗口定位的原因。


②. 定位元素与传统层叠上下文


对于包含有position:relative/position:absolute的定位元素,以及FireFox/IE浏览器(不包括Chrome等webkit内核浏览器)(目前,也就是2016年初是这样)下含有position:fixed声明的定位元素,当其z-index值不是auto的时候,会创建层叠上下文。


知道了这一点,有些现象就好理解了。


如下HTML代码:


<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>



大家会发现,竖着的妹子(mm2)被横着的妹子(mm1)给覆盖了。


下面,我们对父级简单调整下,把z-index:auto改成层叠水平一致的z-index:0, 代码如下:


<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>



大家会发现,尼玛反过来了,竖着的妹子(mm2)这回趴在了横着的妹子(mm1)身上。



为什么小小的改变会有想法的结果呢?



差别就在于,z-index:0所在的<div>元素是层叠上下文元素,而z-index:auto所在的<div>元素是一个普通的元素,于是,里面的两个<img>妹子的层叠比较就不受父级的影响,两者直接套用层叠黄金准则,这里,两者有着明显不一的z-index值,因此,遵循“谁大谁上”的准则,于是,z-index为2的那个横妹子,就趴在了z-index为1的竖妹子身上。


而z-index一旦变成数值,哪怕是0,都会创建一个层叠上下文。此时,层叠规则就发生了变化。层叠上下文的特性里面最后一条——自成体系。两个<img>妹子的层叠顺序比较变成了优先比较其父级层叠上下文元素的层叠顺序。这里,由于两者都是z-index:0,层叠顺序这一块两者一样大,此时,遵循层叠黄金准则的另外一个准则“后来居上”,根据在DOM流中的位置决定谁在上面,于是,位于后面的竖着的妹子就自然而然趴在了横着的妹子身上。对,没错,<img>元素上的z-index打酱油了!


有时候,我们在网页重构的时候,会发现,z-index嵌套错乱,看看是不是受父级的层叠上下文元素干扰了。然后,可能没多大意义了,但我还是提一下,算是祭奠下,IE6/IE7浏览器有个bug,就是z-index:auto的定位元素也会创建层叠上下文。这就是为什么在过去,IE6/IE7的z-index会搞死人的原因。


然后,我再提一下position:fixed, 在过去,position:fixed和relative/absolute在层叠上下文这一块是一路货色,都是需要z-index为数值才行。但是,不知道什么时候起,Chrome等webkit内核浏览器,position:fixed元素天然层叠上下文元素,无需z-index为数值。根据我的测试,目前,IE以及FireFox仍是老套路。


③. CSS3与新时代的层叠上下文

CSS3的出现除了带来了新属性,同时还对过去的很多规则发出了挑战。例如,CSS3 transform对overflow隐藏对position:fixed定位的影响等。而这里,层叠上下文这一块的影响要更加广泛与显著。


如下:


  1. z-index值不为auto的flex项(父元素display:flex|inline-flex).

  2. 元素的opacity值不是1.

  3. 元素的transform值不是none.

  4. 元素mix-blend-mode值不是normal.

  5. 元素的filter值不是none.

  6. 元素的isolation值是isolate.

  7. will-change指定的属性值为上面任意一个。

  8. 元素的-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-colorblue; z-index1; } /* 此时该div是普通元素,z-index无效 */

.box > div > img {

positionrelative; z-index: -1; right: -150px; /* 注意这里是负值z-index */

}


结果如下:



会发现,妹子跑到蓝色背景的下面了。为什么呢?层叠顺序图可以找到答案,如下:



从上图可以看出负值z-index的层叠顺序在block水平元素的下面,而蓝色背景div元素是个普通元素,因此,妹子直接穿越过去,在蓝色背景后面的显示了。


现在,我们CSS微调下,增加display:flex, 如下:


.box { displayflex; }

.box > div { background-colorblue; z-index


本文转载自:http://www.wtoutiao.com/p/195nx9h.html

共有 人打赏支持
L
粉丝 18
博文 166
码字总数 116776
作品 0
成都
程序员
私信 提问
前端面试之层叠上下文(z-index)

什么是层叠上下文 层叠上下文是HTML元素的三维概念,这些HTML元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的z轴上延伸,HTML元素依据其自身属性按照优先级顺序占用层叠上下文...

小诺哥
02/22
0
0
CSS层叠上下文与BFC

CSS中的层叠上下文和BFC是两个很虚但极其重要的概念,影响到网页布局的方方面面。有几篇博文讲得很详细,这里稍加摘录,便于记忆。 CSS层叠上下文 张鑫旭在深入理解CSS中的层叠上下文和层叠顺...

一点灵犀
2016/08/14
45
0
彻底搞懂CSS层叠上下文、层叠等级、层叠顺序、z-index

前言 最近,在项目中遇到一个关于CSS中元素属性的问题,具体问题不太好描述,总结起来就是当给元素和父元素色设置属性和相关属性后,页面上渲染的元素层级结果和我预想的不一样。根据自己之前...

MagicEyes
2018/08/30
0
0
css-层叠上下文与z-index

z-index决定层叠关系吗 众所周知,css会有一个z轴的存在,也就是同一个区域的元素是一个叠加在另外一个上面的。而css中也有一个熟悉:z-index,所以很多人简单的认为,css的层叠关系第一个是...

Kurset
2018/04/14
0
0
前端面试之简述下CSS 中重要的层叠概念

最近在项目的过程中遇到了一个问题,menu-bar希望始终显示在最上面,而在之后的元素都显示在它之下,当时设置了 z-index 也没有效果,不知道什么原因,因此找了一下css有关层叠方面的资料,解...

前端攻城小牛
2018/09/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何开发一款以太坊(安卓)钱包系列2 - 导入账号及账号管理

这是如何开发一款以太坊(安卓)钱包系列第2篇,如何导入账号。有时用户可能已经有一个账号,这篇文章接来介绍下,如何实现导入用户已经存在的账号。 导入账号预备知识 从用户需求上来讲,导...

Tiny熊
今天
2
0
intellJ IDEA搭建java+selenium自动化环境(maven,selenium,testng)

1.安装jdk1.8; 2.安装intellJ; 3.安装maven; 3.1 如果是单前用户,配置用户环境变量即可,如果是多用户,则需配置系统环境变量,变量名为MAVEN_HOME,赋值D:\Application\maven,往path中...

不最醉不龟归
今天
3
0
聊聊ShenandoahGC的Brooks Pointers

序 本文主要研究一下ShenandoahGC的Brooks Pointers Shenandoah Shenandoah面向low-pause-time的垃圾收集器,它的GC cycle主要有 Snapshot-at-the-beginning concurrent mark包括Init Mark(P......

go4it
昨天
2
0
Makefile通用编写规则

#简单实用的Makefile模板: objs := a.o b.o test:$(objs) gcc -o test $^ # .a.o.d .b.o.d dep_files := $(foreach f,$(objs),.$(f).d) dep_files := $(wildcard $(dep_files)) ifneq ($(d......

shzwork
昨天
2
0
《万历十五年》的读后感作文4000字

《万历十五年》的读后感作文4000字: 万历十五年,即1587年,距今已过去432年。在明朝276的历史中,这一年很平淡,并没有什么特别之处。黄仁宇的《万历十五年》一书,有别于其他的历史叙述方...

原创小博客
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部