前言

最近,在项目中遇到一个关于CSS中元素z-index属性的问题,具体问题不太好描述,总结起来就是当给元素和父元素色设置position属性和z-index相关属性后,页面上渲染的元素层级结果和我预想的不一样。根据自己之前的理解,也没找到一个合理的解释。我知道,肯定是我对相关属性的细节理解存在问题,所以结合官方文档和在网上各种搜集整理,明白了其中的原因。写下这篇文章,和大家分享有关CSS中层叠上下文、层叠等级、层叠顺序以及z-index相关的一整套技术细节。

如果存在什么错误或重要遗漏或者有什么疑问,欢迎留言指正、讨论!感谢!

一个“片面”的理解

以往,由于自己使用z-index的频率不大,所以对这个CSS属性存在比较片面的认识。一直认为z-index就是用来描述定义一个元素在屏幕Z轴上的堆叠顺序。z-index值越大在Z轴上就越靠上,也就是离屏幕观察者越近。最后才发现这个认识存在很大的问题:

  1. 首先,z-index属性值并不是在任何元素上都有效果。它仅在定位元素(定义了position属性,且属性值为非static值的元素)上有效果。
  2. 判断元素在Z轴上的堆叠顺序,不仅仅是直接比较两个元素的z-index值的大小,这个堆叠顺序实际由元素的层叠上下文层叠等级共同决定。

要想完全理解一个东西,首先要明白它是什么,也就是它的定义。我们先看看上面提到的层叠上下文、层叠等级、层叠顺序都是什么?定义又太过抽象,后面会再用一个具象的比喻来让你彻底明白它们到底是什么,有什么联系。

什么是“层叠上下文”

层叠上下文(stacking context),是HTML中一个三维的概念。在CSS2.1规范中,每个盒模型的位置是三维的,分别是平面画布上的X轴,Y轴以及表示层叠的Z轴。一般情况下,元素在页面上沿X轴Y轴平铺,我们察觉不到它们在Z轴上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖。

如果一个元素含有层叠上下文,(也就是说它是层叠上下文元素),我们可以理解为这个元素在Z轴上就“高人一等”,最终表现就是它离屏幕观察者更近。

具象的比喻:你可以把层叠上下文元素理解为理解为该元素当了官,而其他非层叠上下文元素则可以理解为普通群众。凡是“当了官的元素”就比普通元素等级要高,也就是说元素在Z轴上更靠上,更靠近观察者。

什么是“层叠等级”

那么,层叠等级指的又是什么?层叠等级(stacking level,叫“层叠级别”/“层叠水平”也行)

  • 在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在Z轴上的上下顺序。
  • 在其他普通元素中,它描述定义的是这些普通元素在Z轴上的上下顺序。

说到这,可能很多人疑问了,不论在层叠上下文中还是在普通元素中,层叠等级都表示元素在Z轴上的上下顺序,那就直接说它描述定义了所有元素在Z轴上的上下顺序就OK啊!为什么要分开描述?

为了说明原因,先举个栗子:

具象的比喻:我们之前说到,处于层叠上下文中的元素,就像是元素当了官,等级自然比普通元素高。再想象一下,假设一个官员A是个省级领导,他下属有一个秘书a-1,家里有一个保姆a-2。另一个官员B是一个县级领导,他下属有一个秘书b-1,家里有一个保姆b-2。a-1和b-1虽然都是秘书,但是你想一个省级领导的秘书和一个县级领导的秘书之间有可比性么?甚至保姆a-2都要比秘书b-1的等级高得多。谁大谁小,谁高谁低一目了然,所以根本没有比较的意义。只有在A下属的a-1、a-2以及B下属的b-1、b-2中相互比较大小高低才有意义。

再类比回“层叠上下文”和“层叠等级”,就得出一个结论:

  1. 普通元素的层叠等级优先由其所在的层叠上下文决定。
  2. 层叠等级的比较只有在当前层叠上下文元素中才有意义。不同层叠上下文中比较层叠等级是没有意义的。

如何产生“层叠上下文”

前面说了那么多,知道了“层叠上下文”和“层叠等级”,其中还有一个最关键的问题:到底如何产生层叠上下文呢?如何让一个元素变成层叠上下文元素呢?

其实,层叠上下文也基本上是有一些特定的CSS属性创建的,一般有3种方法:

  1. HTML中的根元素本身j就具有层叠上下文,称为“根层叠上下文”。
  2. 普通元素设置position属性为static值并设置z-index属性为具体数值,产生层叠上下文。
  3. CSS3中的新属性也可以产生层叠上下文。

至此,终于可以上代码了,我们用代码说话,来验证上面的结论:

栗子1: 有两个div,p.a、p.b被包裹在一个div里,p.c被包裹在另一个盒子里,只为.a、.b、.c设置position和z-index属性

a

b

c

效果:

因为p.a、p.b、p.c三个的父元素div都没有设置z-index,所以不会产生层叠上下文,所以.a、.b、.c都处于由标签产生的“根层叠上下文”中,属于同一个层叠上下文,此时谁的z-index值大,谁在上面。栗子2: 有两个div,p.a、p.b被包裹在一个div里,p.c被包裹在另一个盒子里,同时为两个div和.a、.b、.c设置position和z-index属性

a

b

c

效果:

我们发下,虽然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值大,谁在上面。

什么是“层叠顺序”

说完“层叠上下文”和“层叠等级”,我们再来说说“层叠顺序”。“层叠顺序”(stacking order)表示元素发生层叠时按照特定的顺序规则在Z轴上垂直显示。由此可见,前面所说的“层叠上下文”和“层叠等级”是一种概念,而这里的“层叠顺序”是一种规则。

  1. 在不考虑CSS3的情况下,当元素发生层叠时,层叠顺讯遵循上面途中的规则。 这里值得注意的是:左上角"层叠上下文background/border"指的是层叠上下文元素的背景和边框。
  2. inline/inline-block元素的层叠顺序要高于block(块级)/float(浮动)元素。
  3. 单纯考虑层叠顺序,z-index: auto和z-index: 0在同一层级,但这两个属性值本身是有根本区别的。

对于上面第2条,为什么inline/inline-block元素的层叠顺序要高于block(块级)/float(浮动)元素?这个大家可以思考一下! 其实很简单,像border/background属于装饰元素的属性,浮动和块级元素一般用来页面布局,而网页设计之初最重要的就是文字内容,所以在发生层叠时会优先显示文字内容,保证其不被覆盖。

你要的“套路”

上面说了那么多,可能你还是有点懵。这么多概念规则,来点最实际的,有没有一个“套路”当遇到元素层叠时,能很清晰地判断出他们谁在上谁在下呢?答案是——肯定有啊!

1、首先先看要比较的两个元素是否处于同一个层叠上下文中: 1.1如果是,谁的层叠等级大,谁在上面(怎么判断层叠等级大小呢?——看“层叠顺序”图)。 1.2如果两个元素不在统一层叠上下文中,请先比较他们所处的层叠上下文的层叠等级。 2、当两个元素层叠等级相同、层叠顺序相同时,在DOM结构中后面的元素层叠等级在前面元素之上。

光说不练假把式

对于技术学习,代码展示是最直观最易懂的方式之一。话不多说,直接上代码,我们通过以下几个“栗子”,来进一步验证掌握上面的结论。

栗子3:

效果:

说明:.box1/.box2虽然设置了position: relative,但是z-index: auto的情况下,这两个div还是普通元素,并没有产生层叠上下文。所以,child1/.child2属于元素的“根层叠上下文”中,此时,谁的z-index值大,谁在上面栗子4:

对于栗子1中的CSS代码,我们只把.box1/.box2的z-index属性值改为数值0,其余不变。

.box1, .box2 { position: relative; z-index: 0;}...复制代码

效果:

说明: 此时,我们发现,仅仅修改了.box1/.box2的z-index属性值改为数值0,最终结果完全相反。这时.child2覆盖在了.child1上面。原因是什么呢?很简单:因为设置z-index: 0后,.box1/.box2产生了各自的层叠上下文,这时候要比较.child1/.child2的层叠关系完全由父元素.box1/.box2的层叠关系决定。但是.box1/.box2的z-index值都为0,都是块级元素(所以它们的层叠等级,层叠顺序是相同的),这种情况下,在DOM结构中后面的覆盖前面的,所以.child2就在上面。CSS3中的属性对层叠上下文的影响

CSS3中出现了很多新属性,其中一些属性对层叠上下文也产生了很大的影响。如下:

  1. 父元素的display属性值为flex|inline-flex,子元素z-index属性值不为auto的时候,子元素为层叠上下文元素;
  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。

CSS3中,元素属性满足以上条件之一,就会产生层叠上下文。我们用第1条来做一个简单的解释说明。

栗子5:

parent

child

复制代码

效果:

说明: 我们发现,.child被.parent覆盖了。按照“套路”来分析一下: 虽然.parent设置了z-index属性值,但是没有设置position属性,z-index无效,所以没有产生层叠上下文,.parent还是普通的块级元素。此时,在层叠顺序规则中,z-index值小于0的.child会被普通的block块级元素.parent覆盖。栗子6:

对于上面的栗子,我们只修改.box的属性,设置display: flex,其余属性和DOM结构不变。

.box { display: flex;}

效果:

说明: 当给.box设置display: flex时,.parent就变成层叠上下文元素,根据层叠顺序规则,层叠上下文元素的background/border的层叠等级小于z-index值小于0的元素的层叠等级,所以z-index值为-1的.child在.parent上面。小测试

下面的代码,我会把最终页面渲染的结果放在代码之后,有兴趣的“童鞋”可以分析一下,各个元素的层叠等级,最后来确定这些元素哪个在上哪个在下。

parent

child1
child2

child2-1
child2-2

效果:

vb6 combo根据index显示_彻底搞懂CSS层叠上下文、层叠等级、层叠顺序、z-index相关推荐

  1. 聚齐这三张宝图,搞懂css权重

    CSS权重的知识点算是一个难点,需要掌握所有的选择器,起码看到选择器能分辨出是哪种选择器.我集齐了 3 张图,看看这 3 张图能不能帮你搞懂 CSS 权重(优先级)问题.

  2. 汉字乱码_彻底搞懂这烦人的编码与乱码!

    ❝ 我们平时在处理文本文件或者网络请求时,时不时会遇到乱码的情况,这篇文章就带你彻底搞懂编码和乱码 ❞ 首先,我们要知道,在计算机中,一切都是用0和1来表示的.普通的txt文件.或者客户端发过来的数据 ...

  3. python协程详解_彻底搞懂python协程-第一篇(关键词1-4)

    任何复杂的概念或系统都不是凭空出现的,我们完全可以找到它的演化历程,寻根究底终会发现,其都是在一系列并不那么复杂的简单组件上发展演化而来! by 落花僧 本文通过一系列关键概念,逐步递进理解协程. 0 ...

  4. cad布局怎么用_终于搞懂CAD的布局是个什么玩意儿了!原来布局要这样用

    很多初学的小伙伴都没搞懂CAD布局是怎么一回事儿,其实也没你想像的那么难.今天小编就来跟大家说一说,关于如何新建布局和比例设置等内容,希望对大家有所帮助. 一.布局视口如何定义 1.命令 模型定义布局 ...

  5. $.ligerdialog.open中确定按钮加事件_彻底搞懂JavaScript中的this指向问题

    JavaScript中的this是让很多开发者头疼的地方,而this关键字又是一个非常重要的语法点.毫不夸张地说,不理解它的含义,大部分开发任务都无法完成. 想要理解this,你可以先记住以下两点: ...

  6. 此上下文中不允许函数定义。_彻底搞懂上下文this,轻松应对,一面就过!!!...

    this不仅仅是Javascript的核心内容,也是前端面试的重点,更是在工作中频繁出现的词,那么this是什么?到底this表达了什么?为什么要有this这个词? 彻底搞懂上下文this 1.1 t ...

  7. factorybean 代理类不能按照类型注入_彻底搞懂依赖注入(一)Bean实例创建过程

    点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 上一章介绍了Bean的加载过程(IOC初始化过程),加载完成后,紧接着就要用到它的依赖注入 ...

  8. python from. import失败_彻底搞懂Python 中的 import 与 from import

    以下文章来源&作者:青南(谢乾坤) 摄影:产品经理:kingname 的第一套乐高 你好,我是谢乾坤,前网易高级数据挖掘工程师.现任微软最有价值专家(Python 方向),有6年 Python ...

  9. 最短路算法的证明_彻底搞懂最短路算法

    只想说:温故而知新,可以为师矣.我大二的<数据结构>是由申老师讲的,那时候不怎么明白,估计太理论化了(ps:或许是因为我睡觉了):今天把老王的2011年课件又看了一遍,给大二的孩子们又讲了 ...

最新文章

  1. 关于C语言中的数组指针、指针数组以及二级指针
  2. CString比较相等不得不说的故事
  3. 将Android应用程序打包
  4. windows2008下配置iis时出现错误“由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。”...
  5. Razor Page–Asp.Net Core 2.0新功能 Razor Page介绍
  6. mapper-reducer word count 实例
  7. 实践案例 | 数据可视化报表应用
  8. 阿里云cenos 6.5 模板上安装 docker
  9. 补卡的糟糕经历引发的思考:一点黑客技术让我们不再泄露那么多数据
  10. Java实现二维码生成及图片合成
  11. 三维点云处理(深度学习方法)综述
  12. Scrum-Sprint关键会议的培训
  13. “数据打通”不等于“数据共融”,智能数据营销解决方案了解一下
  14. 华为鸿蒙未来生态,华为王成录:鸿蒙生态构建成功后,未来移动产业20年将属于中国...
  15. 在word2015中的条形图在灰度的情况下不明显
  16. Okra框架(二) 搭建Socket服务器
  17. MySQL之数据库基字符集,中文乱码,大小写敏感,Packet for query is too large
  18. html5考试总结300字,考试总结300字
  19. 龙光城的洋房和惠州的花园
  20. 趣谈 DHCP 协议,有点意思。

热门文章

  1. Angular ngOnChanges hook学习笔记
  2. 什么是前端开发中的viewport
  3. rxjs里subscribeToArray的一个JavaScript模拟实现
  4. Angular TView和LView数据结构
  5. ABAP的数据字典DDIC和Hybris Commerce的类型系统Type system
  6. 一个工作13年的SAP开发人员的回忆:电子科技大学2000级新生入学指南
  7. hybris导出系统已有数据的两种方式
  8. unicode转中文的工具
  9. 无法使用UI configuration的trouble shooting
  10. Why expand does not work for complex note