z-index 层叠上下文的渲染规则
最近我在 Element 里看到了一个 issue:el-image preview bug。之所以导致了这个 Bug,我觉得某种意义上来说就是因为 image 组件的 viewer
(蒙版)模块开发时,没有充分理解 z-index
到底是怎么起作用的。
在此之前,我们先来看一下下面这个例子:
你可以试着变更 fixed
外部的 wrapper
对应的 CSS 样式,甚至是将它挪出来,然后看看效果。
然后你会发现,咦,fixed
尽管在视觉上确实与整个流都无关了,但是在渲染的层级上却依旧受到父级的控制,在默认情况下,它并没有上下级的关系,而是按照一定的规则渲染。
在 MDN 中有一段对于层叠上下文的总结:
层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。
每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。
简单的总结一下层叠上下文的规则:
- 父级有
z-index
的时候,子级的z-index
会受到父级渲染级别的限制 - 只有
positioned element
设置z-index
有效(positioned index
的定义是:非static
的 element) z-index
渲染的优先级从低到高分别是:z-index < 0
/=0
/=auto
or未设置
/z-index > 0
- 默认按照 DOM 树的先后顺序渲染
- 详细的浏览器渲染规则请见参考资料第一篇
那么我们回到 Element 的 Image 组件,看下遮罩的源代码:https://github.com/ElemeFE/element/blob/dev/packages/image/src/image-viewer.vue#L3-L4
我们会发现这里配置的 z-index
实际上是没有意义的,因为当你复合使用的时候,你无法预知父级每一层的 z-index
设置,一旦其中有一层设置了 z-index
,那么这一层中设置的 z-index
将会没有任何意义。
怎么解决呢?我的建议是,但凡遮罩层,都尽量往 body 上插入,至少也需要给用户一个 body 插入的选项,这样可以很好地解决各类因为子元素创建导致的问题。
参考资料:
植入部分
如果您觉得文章不错,可以通过赞助支持我。
如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。