Open lmk123 opened 2 years ago
最近有划词翻译的用户报告了一个 bug,说是语种选择的弹窗被文本框、翻译结果和切换语种的小三角箭头遮挡了,如下图:
我首先检查了它们的 z-index 属性,发现这些遮挡了弹窗的元素都没有设置过 z-index,那为什么会遮挡住设置了 z-index 的弹窗?
z-index
谷歌一番之后,我发现了 CSS 中一个新的概念——堆叠上下文(stacking context)。
上图中的 HTML 结构可以简化为:
<html> <div style="transform: translateY(0px)"> <div>定位元素</div> <div style="position: absolute; z-index: 20">弹窗</div> </div> <div style="position: relative">文本框</div> <div style="transform: translateY(0px)">翻译结果</div> </html>
按照我的理解,这其中只有弹窗设置了 z-index,那么它应该显示在最上方,但事实上它却被文本框和翻译结果遮挡了,原因是:弹窗的父元素是一个新的堆叠上下文,所以弹窗的 z-index 只在它的父元素范围内才生效;而文本框和翻译结果也分别创建了新的堆叠上下文,在 DOM 中排在后面的堆叠上下文会显示在上面。
MDN 上说 position: relative 加上值不为 auto 的 z-index 组合起来才能创建一个新的堆叠上下文,但我在 Chrome 中测试发现,只需要有 position: relative 就会创建一个新的堆叠上下文。
position: relative
auto
知道问题的原因之后,解决方案也就有了:
transform: translateY(0px)
<html> <div style="transform: translateY(0px)"> <div>定位元素</div> </div> <div style="position: relative">文本框</div> <div style="transform: translateY(0px)">翻译结果</div> <div style="position: absolute; z-index: 20">弹窗</div> </html>
transoform
最近有划词翻译的用户报告了一个 bug,说是语种选择的弹窗被文本框、翻译结果和切换语种的小三角箭头遮挡了,如下图:
我首先检查了它们的
z-index
属性,发现这些遮挡了弹窗的元素都没有设置过 z-index,那为什么会遮挡住设置了 z-index 的弹窗?谷歌一番之后,我发现了 CSS 中一个新的概念——堆叠上下文(stacking context)。
上图中的 HTML 结构可以简化为:
按照我的理解,这其中只有弹窗设置了 z-index,那么它应该显示在最上方,但事实上它却被文本框和翻译结果遮挡了,原因是:弹窗的父元素是一个新的堆叠上下文,所以弹窗的
z-index
只在它的父元素范围内才生效;而文本框和翻译结果也分别创建了新的堆叠上下文,在 DOM 中排在后面的堆叠上下文会显示在上面。知道问题的原因之后,解决方案也就有了:
transform: translateY(0px)
和position: relative
transoform
生成的堆叠上下文有效。相关链接