z-index 这个属性表面看上去很简单,但如果你想搞清楚其工作原理的话,其实是有不少值得探讨之处的。本文将从层叠上下文(stacking contexts)和一些实际案例出发,谈一谈 z-index 的内部工作原理。

CSS 为盒模型的布局提供了三种不同的定位方案[1] :

  • 正常文档流

  • 浮动

  • 定位

最后一种方案(特指绝对定位)将会把元素从正常文档流中完全移走,其最终的落脚点将取决于开发者。

通过设置 topleftbottom 和 right 的值,你可以在二维空间中对元素进行定位,但 CSS 同时也允许你使用 z-index 属性[2] 把它放置在三维空间中。

表面看起来,z-index 似乎是一个很简单的属性,你给它设置哪个值,元素就会位于 y 轴的哪个位置,就这样。但它实际上并没有我们想象的这么简单,这个属性背后是一系列决定元素所在层级的规则。

为了保证我们在同一个“频道”上,这里我先普及一些基础概念,之后再解释层叠的相关知识,并在一些场景中体会  z-index[3] 作用的机制。

Z-Index 的基础概念

对于三维空间坐标系,你肯定很熟悉了。x 轴代表水平方向,y 轴代表垂直方向,z 轴则代表我们的目光向页面(屏幕)看进去的时候,各元素的布局情况。

由于屏幕是一块二维平面,我们实际上并没有真的看到 z 轴,更多的是通过透视的形式。具体地说,多个元素共享同一块二维平面时,有的元素在顶部,有的元素在底部,我们由此感受到了 z 轴的存在。

为了决定某个元素在 z 轴方向上的位置,CSS 允许我们为 z-index 属性设置三种值[4]

  • auto(默认值)

  • 整数

  • inherit

我们主要看一下整数值。它可以是正整数、负整数或者 0,值越大,元素就离我们“越近”,值越小,元素自然也就离我们“越远”。

如果两个元素在定位之后共享同一块二维空间,那么在这块空间中, z-index 越大的元素将可能覆盖 z-index 较小的元素。

很显然,上面讲的这些都是非常容易理解的,并且也和我们的直觉相符合。不过,下面的问题恐怕就不是很好回答了:

  • 当设置了定位和 z-index 的元素与一个位于正常文档流中的元素重叠时,哪一个在顶层呢?

  • 一个元素设置定位,另一个元素设置浮动,哪一个在顶层呢?

  • 如果父元素和子元素都设置了定位,会发生什么事?

为了更好地理清这些问题,我们有必要进一步理解与 z-index 工作原理相关的一些概念,也就是层叠上下文、层叠等级和层叠顺序。

层叠上下文和层叠等级

针对层叠上下文和层叠等级[5] ,可能很难给出一个清晰易懂的概念,所以我们这里用通俗的例子来理解。想象一下,现在有一张桌子,上面摆满了各种东西。那么这张桌子就代表了一个层叠上下文,假设还有另一张与之并排的桌子,那么就产生了另一个层叠上下文。

如图所示,层叠上下文 1 指的就是文档根部,而层叠上下文 2 和 3 位于 1 的某个层叠等级中。此外,这两个层叠上下文各自会包含新的层叠等级。

现在想象一下,第一张桌子上面并排摆了四个砖头,这四个砖头上面放着一个玻璃杯,而玻璃杯上面还放着一个水果盘。那么,砖头、玻璃杯、水果盘,各自都处于不同的层叠等级中,但它们共处于“桌子”这一层叠上下文中。

对每一个网页来说,默认都会创建一个层叠上下文[6] ,这个上下文(这张桌子)的根部就是 html 元素,html 元素的所有子元素都会位于这个默认的层叠上下文中的某个层叠等级,就好比东西会摆放在桌子的不同位置上一样。

当你给某个元素设置一个非 auto 的 z-index 时,就会创建一个新的 层叠上下文[7] ,它和它所包含的层叠等级都是独立于其它层叠上下文和层叠等级的,就好比你搬了一张新的桌子放在房间里,它和旧的桌子是互相独立的。

层叠顺序

我们可以通过一个非常简单的例子来理解层叠顺序,这个例子甚至还不需要涉及到 定位元素[8] 。

想象一下,现在有一个非常简单的网页,不考虑默认的 <html><head><body> 等元素,就只需要考虑每个网页至少都会有的一个 <div>。在 CSS 文件中设置 html 的背景颜色为蓝色,设置 div 的背景颜色为红色,并设置宽高。

当加载页面的时候,你觉得会看到什么?

这个自然不用多想,引入眼帘的肯定是一大片的蓝色,同时还有一个此前设置好尺寸的红色块级元素。除非你做了额外的设置,否则这个元素将正常地出现在左上角。

你可能会说“就这?太简单了吧”,不过有一个问题可能不那么简单:为什么红色的块级元素就一定会位于蓝色背景的上层呢?为什么我们看到的就是 div 位于 html 的上层呢?原因是,它们都遵循了层叠顺序的规则。

在这个简单的例子中,根据规则,正常文档流的子块(div)的层级将会高于根元素(html)的背景和边框。我们看到div 位于顶层,这是因为它的层叠等级更高。

虽然上面这个例子只涉及到了两个层叠等级,但实际上,在一个层叠上下文中,一共可能出现七个层叠等级,从最低到最高排列,依次是:

  1. 背景和边框 :形成层叠上下文的元素的背景和边框,它是整个上下文中层叠等级最低的。

  2. Z-Index 为负数 :设置了 z-index 为负数的子元素以及由它所产生的层叠上下文

  3. 块级盒模型:位于正常文档流中的、块级的、非定位的子元素

  4. 浮动盒模型 :浮动的、非定位的子元素

  5. 内联盒模型 :位于正常文档流中的、内联的、非定位的子元素

  6. Z-index 为 0:设置了 z-index 为 0 的、定位的子元素以及由它所产生的层叠上下文

  7. Z-Index 为正数 :设置了 z-index 为正数的、定位的子元素以及由它所产生的层叠上下文,它是整个上下文中层叠等级最高的

这七个层叠等级就构成了层叠顺序的规则。符合层叠等级七的元素,会比层叠等级在一到六的元素更“贴近我们”,符合层叠等级五的元素,会比层叠等级二的元素更“贴近我们”,以此类推。

第一次学习这些层叠规则的时候,我感觉收获了很多新的东西。如果只着眼于层叠等级二、六和七(也就是涉及到 z-index 的等级),那么大部分时候,我们对于 z-index 的理解是正确的。正的 z-index 的层级比 0 要高,而 0 又比负的要高,一切都符合直觉,可能大多数人到这里就不继续往后探究了。

我之前就是这样,在看到这些规则之前,以为除了正的和负的 z-index ,其它情况都可以看作是 z-index 为0 —— 不过现在我们很清楚了,这种想法是错误的。事实是,大部分元素的层级都要低于 z-index:0

还有一个有趣的细节是,非定位的元素实际位于四种不同的层叠等级中。乍一想觉得很奇怪,不过其实这是很合理的。假设所有的非定位元素都位于同一个层叠等级,那么我们就没办法在 div (块级盒)上看到文本(内联盒)了。

来看个案例

我前面提到过很多次,当你给一个元素设置非 auto 的 z-inde 时,会创建一个新的、完全独立的层叠上下文。

重新回顾一下之前拿桌子做比喻的案例。一开始的时候,我们的桌子上摆满了四块砖头,上面是一个玻璃杯,再上面是一个水果盘。现在,假设又有一张新的桌子,它摆放的东西和旧桌子差不多,唯一的不同是,新桌子少了一个水果盘。

不难想象,旧桌子的水果盘是整个房间中位于最顶层的物品(它有最大的 z-index),不过,如果把旧桌子以及它上面的所有东西整体搬到地下室呢?此时,水果盘的层级会比新桌子上的每一个物品都要低,这是因为,放置水果盘的旧桌子整体已经低于新桌子了。

对于网页上的定位元素来说,其实道理是一样的。假设有如下代码,思考一个问题:div.two 和 div.four,哪个在上哪个在下?

HTML:

<div class="one"><div class="two"></div><div class="three"></div>
</div>
<div class="four"></div>

CSS:

div {width: 200px;height: 200px;padding: 20px;
}.one, .two, .three, .four {position: absolute;
}.one {background: #f00;outline: 5px solid #000;top: 100px;left: 200px;z-index: 10;
}.two {background: #0f0;outline: 5px solid #000;top: 50px;left: 75px;z-index: 100;
}.three {background: #0ff;outline: 5px solid #000;top: 125px;left: 25px;z-index: 150;
}.four {background: #00f;outline: 5px solid #ff0;top: 200px;left: 350px;z-index: 50;
}

尽管 div.two 有更高的 z-index(100),但在页面上,它的层级实际上比 div.four (z-index 为50)要低。下图就是页面元素的层级情况,根据黑色和黄色边框,我们可以区分每个元素生成的不同的层叠上下文。

由于 div.two  位于 div.one 中,所以它的 z-index 是和 div.one 的层叠上下文相关的,也就是说,实际表现出来的 z-index 是下面这样的:

  • .one —— z-index = 10

  • .two —— z-index = 10.100

  • .three —— z-index = 10.150

  • .four —— z-index = 50

div.one 和内部包含的一切将会在层级上低于 div.four,无论给  div.one 的子元素设置多大的 z-index,子元素的层级都无法超过 div.four

看到这个例子是不是有一种熟悉的味道?我也曾经被 z-index 这么坑过一两次。我们都曾疑惑一个问题,为什么一个 z-index 非常大的元素,在层级上始终无法超过一个 z-index 比它小很多的元素?相信在学习了这些案例之后,你已经豁然开朗了。

总结

在最初学习 z-index 的时候,我们都会认为它很简单,这不就是代表元素在 z 轴上的位置吗?不过我们现在知道了,事情远没有这么简单。深入理解 z-index[9] 一文也揭示了 z-index 背后一些原理层面的东西,包括层叠上下文,层叠等级以及一系列决定元素的层叠顺序的规则。

最后,记住一个很重要的结论:定位元素可以创建新的层叠上下文,在这个上下文中的所有层叠等级,都会高于或者低于另一个层叠上下文的所有层叠等级。

拓展阅读

  • What No One Told You About Z-Index by Philip Walton

  • The Z-Index CSS Property: A Comprehensive Look on Smashing Magazine

  • How Well Do You Understand CSS Positioning?

  • The stacking context on Mozilla Developer Network

  • Z-Index And The CSS Stack: Which Element Displays First?

原文地址:What You May Not Know About the Z-Index Property

作者:Steven Bradley

译者:Chor

1. JavaScript 重温系列(22篇全)

2. ECMAScript 重温系列(10篇全)

3. JavaScript设计模式 重温系列(9篇全)

4. 正则 / 框架 / 算法等 重温系列(16篇全)

5. Webpack4 入门(上)|| Webpack4 入门(下)

6. MobX 入门(上) ||  MobX 入门(下)

7. 120+篇原创系列汇总

回复“加群”与大佬们一起交流学习~

点击“阅读原文”查看 120+ 篇原创文章

【CSS】关于 z-index,你可能一直存在误区相关推荐

  1. HTML中z index属性是用来,css中z-index 属性与用法详解

    Z-index属性决定了一个HTML元素的层叠级别.元素层叠级别是相对于元素在Z轴上(与X轴Y轴相对照)的位置而言.一个更高的Z-index值意味着这个元素在叠层顺序中会更靠近顶部.这个层叠顺序沿着垂 ...

  2. html设置z index.html,CSS中z-index属性的使用方法和示例介绍

    怎么使用CSS z-index属性?下面本篇文章就来给大家浅谈一下CSS z-index属性的使用方法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. z-index属性介绍只有设置 ...

  3. js怎么设置z index.html,HTML5 Canvas set z-index

    j0kEli Stone提出了一个问题:HTML5 Canvas set z-index,或许与您遇到的问题类似. 回答者markE给出了该问题的处理方式: Yes..kind of yes. You ...

  4. CSS基本知识总结(HTML+CSS)

    HTML 1.网页组成 网页是由HTML(文字,图片,输入框,按钮,视频,音频...)组成的 2.网页规范(W3C) 结构标准:制作网页必须按照HTML的标准结构去写网页(用于对网页元素进行整理和分类 ...

  5. css索引_CSS中的Z索引:它是什么以及它做什么

    css索引 什么是Z索引? (What is a Z Index?) Z Index (z-index) is a CSS property that defines the order of ove ...

  6. Cordova工程index.html/index.css/index.js结构及关键代码

    Cordova工程index.html/index.css/index.js结构及关键代码 1. index.html 2. index.css (1)横竖屏的判断方法: (2)深色模式适配 3. i ...

  7. [转]深入理解CSS中的层叠上下文和层叠顺序

    http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/ 零.世间的道理都是 ...

  8. CSS定位(postion)和移动(float)

    5.定位和移动: Positioning(定位) CSS定位属性允许你为一个元素定位.它也可以将一个元素放在另一个元素后面,并指定一个元素的内容太大时,应该发生什么. 元素可以使用的顶部,底部,左侧和 ...

  9. 1、CSS 定位 (Positioning)

    position 属性指定了元素的定位类型. CSS 定位属性 属性 描述 position 把元素放置到一个静态的.相对的.绝对的.或固定的位置中. top 定义了一个定位元素的上外边距边界与其包含 ...

  10. 三小时学会css(菜鸟教程精华版)【中】

    三小时学会css 上期传送门 CSS 盒子模型(Box Model) CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容. 盒模型允许我们在其它元素和周围元素边 ...

最新文章

  1. copyTo函数、随机数产生器 RNG、轮廓的特征矩 Moment、cvGet2D函数
  2. poj 3384 Feng Shui 半平面交
  3. G - Tiling FZU - 2040(未解决)
  4. 猎鹰spacex_我从SpaceX中学到的关于开源的一切
  5. 利用nginx集群式部署服务器中,数据同步问题
  6. openerp mysql_Odoo字段(Fields)总结-至2020全
  7. jboss下载(jboss安装与配置)
  8. python爬取设置了权限的qq空间_Python爬取qq空间说说的实例代码
  9. 计算机网络(谢希仁版)知识点汇总
  10. 修改mysql的authen_MySQL连接抛出Authentication Failed错误的分析与解决思路
  11. 用计算机来猜星座,[转]实用推荐---三个问题猜出对方的星座
  12. vue的axios两种写法(不知道对不对,仅供参考)
  13. PHP可视化告警规则引擎,开源可视化规则引擎 决策引擎与规则引擎有什么区别?...
  14. 绝版 ~ 原来 Python 画画可以这么简单
  15. python两列时间间隔计算器_计算两列之间的Pandas DataFrame时间差异(以小时和分钟为单位)...
  16. diy nas配置推荐2019_5款NAS 系统横向测评,看看哪款最适合你!
  17. vanish_3.0_ban
  18. 【Android-Kotlin-Volley】图片画廊学习笔记
  19. ftp给服务器上传文件,ftp上传文件给服务器
  20. 【软考中级】多媒体应用设计师复习笔记第六章

热门文章

  1. android蓝牙浅析
  2. C# 使用Redis实现粉丝好友互粉数据存储和查询
  3. Hdu 1496 Equations(巧妙哈希)
  4. 感恩节,感谢大家的一路相伴
  5. 中国民商·商人第一村水稻专属种植基地落户永吉县
  6. 「目前全网唯一2万字长文」从JS上下文到Chromium源码的极限拉扯!!兄弟姐妹们接好了!!...
  7. 【巨杉数据库SequoiaDB】24 Hours , 数据库研发实录
  8. 面试中,被问到“哑口无言”的瞬间怎么办?
  9. 免费的高匿名爬虫代理池不求人|高可用、高匿名、代理池详解及搭建推荐
  10. 运营商精准大数据——主动出击 精准获客_客户_实时数据