多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[toc] ## 什么是层叠上下文 层叠上下文,英文为`stacking context`, 当一个元素具备层叠上下文,这个元素在**Z轴**上就"高人一等" 我们可以把层叠上下文理解为一种"层叠结界",自成一个**小世界**(**每一个小世界由7个阶层组成,发生重叠时,阶层高的覆盖阶层低的**)。 在这个小世界可能有其他的"层叠结界",而自身也可能处于其他"层叠结界"中。 ### 创建层叠上下文 和BFC块状格式化上下文一样,层叠上下文也基本上是由一些特定的CSS属性创建的,主要分为3个流派。 - 天生派:页面根元素天生具有层叠上下文,称为根层叠上下文 - 正统派:z-index值为数值的定位元素的传统“层叠上下文” - 扩招派:其它CSS3属性 #### zindex:auto 没有手动指定一个z-index值的话,会设置为auto,在层叠顺序上位于第6阶 因为所有元素都处于`根元素`这么个层叠上下文中,故所有元素默认z-index皆为auto #### 定位元素与传统层叠上下文 当元素定位时(absolute/fixed/relative)时,只要`z-index`的值**不**为auto,那么这个元素就会成为一个新的层叠上下文,形成层叠结界。 另外需要注意的是**Chrome**下,只要是**fixed**固定定位的元素就会生成一个新的层叠上下文。 #### CSS3新属性创建层叠上下文 满足以下CSS3属性值的都会创建层叠上下文 1. 元素为flex布局元素(父元素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属性值为上面的2~6的任意一个(如will-change:opacity、will-change:transform等) 8. 元素的-webkit-overflow-scrolling设为touch CSS3新属性创建的层叠上下文**除却**flex,其它**都**不能使用`z-index`,他们的层叠顺序为第六阶。 ## 什么是层叠水平 层叠水平,英文为`stacking level`, 决定了同一个层叠上下文中元素在**Z轴**上的**显示顺序**。 (这意味着一个层叠上下文**中的**元素不能脱离"层叠结界"和另外一个层叠上下文中的元素较量层叠水平,而是由层叠上下文元素之间相互较量) >[danger] 层叠水平!==z-index, > >**z-index**只在**定位元素**和**flex**盒子的孩子元素身上有效 > >而**层叠水平**所有的元素的存在(至少都有一个根元素作为层叠上下文) > ### 层叠顺序 层叠顺序是层叠水平的具体实现规则,英文称之为`stacking order` 层叠顺序一共**7层**,由下层到上层依次为 -->层叠上下文のbackground/border -->负z-index -->block块状水平盒子 -->float浮动盒子 -->inline水平盒子 -->z-index:auto(比如absolute的元素不设置z-index)或则z-index:0,又或则不依赖z-index的层叠上下文 -->正index >**注意:** >inine水平盒子指的是包括inline/inline-block/inline-table元素的层叠顺序,它们都是同等级别的 > #### z-index为0和auto 第六阶层需要注意的是, 元素一旦成为定位元素,其z-index会**自动生效**,也就是`z-index:auto`,它相当于就是`z-index:0`, **但是**z-index:0和z-index:auto有一点本质上的不同在于: z-index:0会生成一个**新**的层叠上下文 ![](https://box.kancloud.cn/ce90f9da7f12bca052756785763e088e_896x403.png) (可以发现两个div中的img因为处于同一个层叠上下文中,So层叠顺序由z-index决定,故我们看见的是第一个div中的img) 但如果我们将第一个div的zindex设置为0 ![](https://box.kancloud.cn/91e4f95a698cfb6c0332405e7b43524b_894x404.png) (可以发现img中的z-index不管用了,层叠按照层叠准则的第二条,后来居上原则进行) 这是为什么呢? 因为`z-index:0`生成了一个新的层叠上下文,对内部(这个新的层叠上下文里的元素)而言,就形成一个**结界**,里面的元素无法再和外面的层叠水平进行**直接**较量,而是由各自的头头进行较量 而此时第一个img的头头也就是第一个div的z-index为0,而第二个img的头头div此时没有设置z-index,z-index自动生成值为auto, 然auto和0的层叠水平是一样的,故层叠顺序由`层叠准则`的第二条决定,谁在后面谁就在上面。 #### z-index为负值 z-index为负值时有不少应用, 比如css3属性创建的层叠上下文是不能使用z-index值调整层叠顺序的(只有定位元素和flex子项可),但我们可以调整那一个不是由css3属性创建的层叠上下文的元素的z-index值为负值从而达到目的 >[info] css3属性创建的层叠上下文元素本身处于第六阶,而z-index负值处于第二阶 ![](https://box.kancloud.cn/e0d14eeb9a10b9c623ff262a14b0f1db_891x403.png) ![](https://box.kancloud.cn/fededc0ce183947e5e8f52f746dd71b6_892x395.png) 另外 ![](https://box.kancloud.cn/d310b9a802097ce9cead798e4896d0cb_740x405.png) 可以发现图片跑到包裹它的div盒子的下边去了,为什么呢? 因为此时div元素与img是处于同一层叠上下文中的,故谁处于**7层层叠顺序**的上层,谁就在上面。 而`block元素层`是高于`z-index:负值层`的,故图片在下面 但如果此时我们让这个div元素形成一个新的层叠上下文,那么此时img就成了这个新的层叠上下文中的一部分, 那么此时div就算作第一阶`层叠上下文のbackground/border`,是要低于第二阶的`负z-index`的 ![](https://box.kancloud.cn/76860c4c6f24fade251245cb86751ebd_736x405.png) (Chrome下fixed固定定位的元素无需z-index:非auto,就能生成一个层叠上下文) ### 层叠准则 当元素发生层时,其覆盖关系遵循下面两条准则 - 谁大谁上:当具有明显的层叠水平标识的时候,如生效的z-index属性值,在同一个层叠上下文领域,层叠水平值大的哪一个覆盖小的那个一个。 - 后来居上:当元素的层叠水平一致、层叠顺序相同的时候,在DOM流中处于后面的元素会覆盖前面的元素 ## 总结 小世界——层叠上下文 每一个小世界拥有7个阶层,同一个小世界中,两个元素发生重叠时,处于高阶层的元素会覆盖低阶层的元素。 如果两个元素阶层也是一样的,那么会根据`层叠准则`进行覆盖。