在CSS 2.1 Section 9.9.1 - Specifying the stack level标准中, 第一句话就说了,对于一个定位的box,z-index属性确定了这个元素在当前堆叠上下文中的堆叠层级同时是建立一个新的堆叠上下文。
没有z-index的堆叠
如果没有元素拥有z-index元素,浏览器渲染元素的顺序是这样的:
- 根元素的背景和边框
- 正常流中的块元素
- 浮动的块元素
- 正常流中的内联元素
- 定位元素
根据1->2->3->4->5的顺序绘制, 越往前越先绘制也就在越后面。
z-index来了
如果有了z-index, 这一属性会影响元素的渲染情况,原因是z-index属性会带来堆叠上下文(stacking context)。在一个堆叠上下文中子元素根据下述的规则进行渲染。
值得注意的是子堆叠上下文只在父元素中有意义。父堆叠上下文中的一个个子堆叠上下文是原子性的,自成单元的。
渲染顺序:
- 堆叠上下文的背景和边框
- 负的子堆叠上下文
- 流内非内联,非定位的子孙元素(normal 流中的块元素)
- 非定位的浮动
- 子堆叠上下文中z-index为0的和定位的z-index为0的元素
- 正的子堆叠上下文
怎么样会产生堆叠上下文
一开始就说到的定位元素设置一个z-index(z-index=0也会产生堆叠上下文,与定位元素z-index设置为auto都是第5级)就会产生一个堆叠上下文。
产生堆叠上下文的方式:
- 根元素
- z-index不为0的定位元素
- opacity小于1的元素
- transform不为none的元素
- mix-blend-mode 不是normal的元素
- filter不是none的元素
- isolation设置为isolate的元素
- position fixed有可能自带这一特性
- 在will-change中设置上述任意属性
- -webkit-overflow-scrolling设置为touch的元素
跨过这些坑
一般情况下不会遇到z-index的问题, 在拖拽以及元素动画的时候要注意。是不是由于堆叠上下文,让元素层次不对,出现了显示bug。