看似简单的z-index会让你吐血

看似简单的表象实际上并没有想象的简单。最近不知道啥情况,同事之间流行了一句话“这还不简单啊”。甭管遇见什么问题都是先抛出这句话出来。除了增加自信之外还附带了震慑菜鸟的功能,不过我是不敢苟同这句话。闲话不多说,老规矩原创文章有妹子镇楼。养眼的同时还能提升血压增加血流量,让脑子转的更快。

少女前线 莫辛纳甘(来自萌娘百科)

先从简单的定义开始理解。z-index属性的定义是设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。很简单的一句话,字面上理解就是z-index来决定谁在上面谁在下面的属性。尤其是对于有一定Photoshop基础的人来说理解这点很是简单。

专业点来说,该属性设置一个定位元素沿 Z轴的位置,Z轴定义为垂直延伸到显示区的轴。如果为正数,则离用户更近,为负数则表示离用户更远。这条Z轴垂直于显示器确“看不见”。和PS中的图层的意思很是相近。每一个DOM元素都会有一个z-index值。

属性必然会有可能的值,z-index属性的值比较简单,只有三种取值可能。

  • auto:这是默认值。堆叠顺序与父元素相等。
  • number:整数值,设置元素的堆叠顺序。(可设置负数
  • inherit:父元素继承 z-index 属性的值。

相信看到这里,各位大神都会觉得。我是在复制一些网上的信息过来拼凑成文章而已。我只能嘿嘿嘿嘿笑下。装逼时间还未到……

嘿嘿嘿

有些程序猿,尤其是后端大神对于我们前端工程师总是嗤之以鼻,言语内外总是带着一点点的优越感。哥我从来不信邪,都说CSS简单,可我认为越是简单的东西越是难掌握。因为简单会让人不去深入钻研,或是潜意识去忽略一部分东西,而这些东西有可能就是看上去简单的知识最核心的内容。

当我们在百度的搜索框做了一点点操作之后,就会有一个下拉框。只有搜索有一定热度的词才会被放到备选下拉框中。当我输入z-两个字符的时候就会跳出如下图的内容:

其实我想笑,我知道是什么的弱智原因造成的无效。记得曾经有一位我比较崇拜的编程开发大神曾经很认真的问过我这个问题。真不知道那些偏激后端大神们的优越感从什么地方来的。在这里我就代表前端那些纯玩CSS的人来告诉那些看不起前端的人,让他们知道在不同的知识领域有不同的知识深度,那些你看上去很“肤浅”很“幼稚”的东西会让你焦头烂额。

是时候展现真正的技术了

要想彻底的把z-index搞的很清晰,我们必须先从几个概念开始了解。。接下来会有大段的英文引用和蹩脚的翻译,请勿喷饭!

层叠上下文(stacking context),在MDN中的描述是

引文原文
Stacking context is the three-dimensional conceptualization of HTML elements along an imaginary z-axis relative to the user who is assumed to be facing the viewport or the webpage.HTML elements occupy this space in priority order based on element attributes.

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

也就是上文开头在解释概念的时候说的垂直于显示器的看不见的Z轴。

层叠等级(stacking level)
层叠等级顺序决定了同一个层叠上下文中元素在z轴上的显示顺序。其实也有叫层叠水平的,不过我还是习惯叫它层叠等级。

层叠顺序(stacking order)
关于层叠顺序网络上可以找到一张很著名的图,不过图有点点错误。为了节省时间我还是引用吧。

image.png

为什么说图有点错误呢?按照 W3官方 的说法,准确的 7 层为:

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

蹩脚的翻译

  1. 形成层叠上下文环境的元素的背景与边框
  2. 拥有负 z-index 的子堆叠上下文元素 (负的越高越堆叠层级越低)
  3. 正常流式布局,非 inline-block,无 position 定位(static除外)的子元素
  4. 无 position 定位(static除外)的 float 浮动元素
  5. 正常流式布局,inline-block元素,无 position 定位(static除外)的子元素(包括 display:table 和display:inline )
  6. 拥有 z-index:0 的子堆叠上下文元素
  7. 拥有正 z-index: 的子堆叠上下文元素(正的越低越堆叠层级越低)

一个普通元素具有了层叠上下文,其层叠顺序就会变高。那它的层叠顺序究竟在哪个位置呢?这里需要分两种情况讨论:

如果层叠上下文元素不依赖z-index数值,则其层叠顺序是z-index:auto可看成z:index:0级别;
如果层叠上下文元素依赖z-index数值,则其层叠顺序由z-index值决定。

所以为什么定位元素会层叠在普通元素的上面?其根本原因就在于,元素一旦成为定位元素,其z-index就会自动生效,此时其z-index就是默认的auto,也就是0级别,根据上面的层叠顺序表,就会覆盖inlineblockfloat元素。

而不支持z-index的层叠上下文元素天然z-index:auto级别,也就意味着,层叠上下文元素和未设置z-index的定位元素是一个层叠顺序的,于是当他们发生层叠的时候,遵循的是“后来居上”准则。

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

如何去比较上下文的层级关系呢?在同一个层叠上下文中,则根据7阶层叠等级比较。若两元素在同一层叠水平,则后来居上,即在DOM流中处于后面的元素会覆盖前面的元素。

在不同的层叠上下文中,则直接比较父元素的层叠水平:
若父元素的z-index不同,则z-index数值越大,越在上面。
若父元素的z-index相同,则在DOM流中处于后面的元素会覆盖前面的元素。

注:
比较时,先看两个元素是不是在同一个父元素之下,若不是,则一层层往上找,直到找到其祖先元素在同一级时停止。然后,再依次往下寻找各自的子元素,找到第一个是层叠上下文元素的子元素后进行比较。

子元素的 z-index 值只在父级层叠上下文中有意义。即父元素的z-index 低于父元素另一个同级元素,子元素 z-index再高也没用。

z-index值为负的元素比较特殊,他们会先被绘制,意味着他们可以出现在其他元素的后面,甚至出现在它的父元素后面。但是必要条件是该元素必须与父元素处于同一层,并且父元素不是这个层的根元素。

罗里吧嗦的说了半天,不知道各位看官对于z-index失效的原因有没有搞明白?

如何让DOM元素去“触发”层叠上下文呢?根据 MDN的说法就是:

只有这些就算是理解了z-index了么?开什么玩笑,没点干货敢出来写东西么?

装逼特效全开

我们写3个<div>元素,然后每个<div>元素里面都有一个<span>元素,每个<span>元素都有个背景色,并且使用absolute定位,为了能更清楚地看到z-index的效果,添加一些其他的样式。第一个<span>元素的z-index值为1,其他两个没有设置。

<!--html-->
<div> 
  <span class="red">Red</span>
 </div> 
<div> 
  <span class="green">Green</span> 
</div>
<div> 
  <span class="blue">Blue</span>
</div> 
/*css*/
.red, .green, .blue {
  position: absolute;
  width: 100px;
  color: white;
  line-height: 100px;
  text-align: center;
}
.red {
  z-index: 1;
  top: 20px;
  left: 20px;
  background: red;
}
.green {
  top: 60px;
  left: 60px;
  background: green;
}
.blue {
  top: 100px;
  left: 100px;
  background: blue;
}

我们会得到像下图一样的东西

好玩的来了:尝试把红色的<span>元素放到其他两个元素后面,但是必须遵守下面的规则:

  • 不能修改HTML的内容
  • 不能增加或修改任何元素的z-index属性
  • 不能增加或修改任何元素的position属性

有点难度么?还是觉得不可能呢?如果你已经找到了问题的解决方案,恭喜你看文章看的很仔细,知识细节的掌握很是完美,如果想了半天还是找不到办法的话,就先请自己的优越感和自信心收一收吧,我们接下来进行。

解决方案很简单,你只需要给红色的<span>标签增加一个opacity小于1,像下面这样:

div:first-child {
  opacity: .99;
}

其实在上文中DOM元素去“触发”层叠上下文的第四项就已经告诉了我们答案了啊。复习下上文介绍的层叠上下文等概念的知识,有助于我们总结为什么红色的<span>会去到下面:

  • 开始有两个层,一个由根节点产生,一个由设置了z-index:1并且position:absolute的红色<span>产生。
  • 当我们设置了opacity时,产生了第三个层,并且第三个层把红色<span>产生的层包裹了,意味着刚开始的z-index的作用域只在第三个层里面。
  • 而所有的<div>都没有定位或者z-index,所以他们的堆叠顺序按照HTML出现顺序排列,于是第三个层就去到下面。

报告完毕~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容