Wonderjar's Blog

zindex堆叠问题

2018-03-29

不一定需要zindex

首先zindex主要用于非static的position,static定位的一个个铺开也不需要调整层级。
但对于这几类,也不是总需要zindex,我觉得有两点需要知道,
1.非static定位的元素有一个隐式的层级,居于static定位元素之上
2.html中后边的元素有一个隐式的层级,居于前边元素之上
3.其实这个也算后来居上,子元素居于父元素之上
比如运行这段html,

1
2
3
4
5
6
7
8
<div style="width: 300px; height: 300px; border: 2px solid black; position: relative;">
<div style="width: 200px; height: 200px; background-color: red; position: absolute;">
</div>
<div style="width: 100px; height: 300px; background-color: yellow;">
</div>
<div style="width: 300px; height: 100px; background-color: blue; position: relative; bottom: 300px;">
</div>
</div>

效果是这样,

zindex作用

好了,当我们确实需要调整层级的时候,zindex就能发挥作用
数字越大越在上,这个很简单,但需要明确定位到底是以什么作为参考定位
先说结论,当我们要比较两个dom节点,那么从它们自身开始向父节点(不超过他们的共同父节点)寻找,找到各自第一个非static定位且设置过zindex的节点,然后比较他们的zindex,没有视为0,先后顺序同样有隐式层级
可以用下面三段代码来测试这一点

1
2
3
4
5
6
7
8
<div style="width: 300px; height: 300px; border: 2px solid black; position: relative;">
<div style="width: 200px; height: 200px; background-color: red; position: absolute;">
<div style="width: 100px; height: 100px; background-color: yellow; z-index: 1;">
</div>
</div>
<div style="width: 300px; height: 100px; background-color: blue; position: absolute; top: 50px;">
</div>
</div>

1
2
3
4
5
6
7
8
<div style="width: 300px; height: 300px; border: 2px solid black; position: relative;">
<div style="width: 200px; height: 200px; background-color: red; position: absolute;">
<div style="width: 100px; height: 100px; background-color: yellow; z-index: 1; position: absolute;">
</div>
</div>
<div style="width: 300px; height: 100px; background-color: blue; position: absolute; top: 50px;">
</div>
</div>
1
2
3
4
5
6
7
8
<div style="width: 300px; height: 300px; border: 2px solid black; position: relative;">
<div style="width: 200px; height: 200px; background-color: red; position: absolute; z-index: 0;">
<div style="width: 100px; height: 100px; background-color: yellow; z-index: 1; position: absolute;">
</div>
</div>
<div style="width: 300px; height: 100px; background-color: blue; position: absolute; top: 50px;">
</div>
</div>

可能引起zindex混乱的原因

上面说道的,其实还只是层叠中的一小部分东西。
说到要比较两个节点,其实是必须在同一个层叠上下文中去比。
这个层叠上下文就是两个节点的共同父节点所在的层叠上下文,为了找到这两个节点在这个层叠上下文中的位置,需要从这两个节点开始各自往上找(最远不能到公共父节点),找到最后一个能产生层叠上下文的节点,然后就比较这两个节点的位置。
这里有点子凭父贵或者子凭父贫的意思,就是如果子节点处在一个很下层的层叠上下文中,当它去上层比较时,其实只看它在最上层的层叠上下文中所处的位置。

叠加上下文是什么?
Reference https://www.bennadel.com/blog/3371-stacking-context-is-the-key-to-understanding-the-css-z-index.htm
It quarantines the CSS z-index values of its descendant nodes. In other words, it prevents the z-index values in the local DOM tree from interacting with the layering outside of the local DOM tree. And, from the larger document perspective, all elements within a stacking context are treated as if they have the same z-index:

叠加上下文怎么产生?
Reference https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
The stacking context
In the previous part of this article, Using z-index, the rendering order of certain elements is influenced by their z-index value. This occurs because these elements have special properties which cause them to form a stacking context.

A stacking context is formed, anywhere in the document, by any element in the following scenarios:

Root element of document (HTML).

  • Element with a position value “absolute” or “relative” and z-index value other than “auto”.
  • Element with a position value “fixed” or “sticky” (sticky for all mobile browsers, but not older desktop).
  • Element that is a child of a flex (flexbox) container, with z-index value other than “auto”.
  • Element with a opacity value less than 1 (See the specification for opacity).
  • Element with a mix-blend-mode value other than “normal”.
  • Element with any of the following properties with value other than “none”:
    • transform
    • filter
    • perspective
    • clip-path
    • mask / mask-image / mask-border
  • Element with a isolation value “isolate”.
  • Element with a -webkit-overflow-scrolling value “touch”.
  • Element with a will-change value specifying any property that would create a stacking context on non-initial value (see this post).

Within a stacking context, child elements are stacked according to the same rules previously explained. Importantly, the z-index values of its child stacking contexts only have meaning in this parent. Stacking contexts are treated atomically as a single unit in the parent stacking context.

在一个层叠上下文中,元素的顺序又是什么?
Reference http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/
从上到下,
正zindex
zindex:auto/zindex:0/不依赖zindex的层叠上下文
inline/inline-block水平盒子
float浮动盒子
block块盒子
负zindex
层叠上下文,background/border

要注意其中层叠上下文本身居于最下

组件思考

有时一个很深层的组件需要一个弹出层,若是弹出层设计在这个深层组件中,也许会受到父组件设定层叠上下文的影响,就没法展示一个全屏最上层的弹出层,不是”坑爹”,而是被”爹坑”。
所以没必要的时候不要滥用zindex,要看创建一个新的层叠上下文会带来的负面影响
另一方面,可以做一些公共的弹出层组件放在上层,通过事件的方式触发弹出层