[BUGCASE]层叠上下文和z-index属性使用不当引发的文本被遮挡的问题
一、问题描述
- 在一个fixed-data-table(一个React组件)制作的表格中,需要给表头的字段一个提示的特效,所以做了一个提示层
- 这个提示层被固定(拖动表格的水平滚动条时固定)的表格列遮住
- 无论设置该提示层的z-index为多大,都不能让其在固定表格列列之上
效果如下:
二、问题分析
通过对页面的DOM层级进行分析,把有可能影响层级的部分抽出来:
主要有以下几个部分会影响到元素的层级(关于设置了哪些属性会影响层级请看后面的附),下面逐一分析:
- A元素和B元素都有一个样式是position:absolute;,因此有可能影响到层级(其实不会影响,因为没有设置z-index)
- D元素有以下样式可能会影响到层级:position: absolute; z-index: 0; transform: translate3d(0px, 0px, 0px);
- C元素有以下样式可能会影响到层级: opacity: 1; transform: translate(-50%, 0); z-index: 99999999; position: absolute;
- E元素的样式: position: absolute; width: 140px; z-index: 2; transform: translate3d(0px, 0px, 0px);
A和B是处于同一个层叠上下文(由其父元素创建的)中的,这样的话,应该是后面的元素(B)会覆盖前面的元素(A),但现在并不是这样。
原因:A最近的子元素E创建的层叠上下文(z-index:2)比B最近的子元素C(z-index:0)创建的层叠上下文的层级高。
结论:这就导致了B的所有子元素(当然也包括我们的提示层C)都会比A的层级低,所以C的z-index设置为多大都没用。
三、问题抽象
本来是一个应用场景中的问题,我们可以抽象为以下问题:
已知:
(1) 两个兄弟元素A和B,A的直接子元素E,其层级是2
position: absolute;z-index:2;transform: translate3d(0px, 0px, 0px);
(2) B的直接子元素D,其层级是0
position: absolute;z-index:0;transform: translate3d(0px, 0px, 0px);
(3) D下面还有一个子元素C,层级很大
z-index:9999
(4) 并且transform属性不能改,也不能去掉
问:
怎么实现C在A的上面(层级上的上面),B在A的下面?
HTML结构大概这样:
<div class="div-a">A is here
<div class="div-e">E is here</div>
</div>
<div class="div-b">B is here
<div class="div-d">D is here
<div class="div-c">C is here</div>
</div>
</div>
四、缺陷归类
样式缺陷
五、建立演示
以下是问题定位过程中建立的几个Demo(其中最后一个是最合理的Demo,想直接看结论的可直接看最后一个Demo):
六、解决方案
单纯从抽象出来的问题来看,解决的方案是D不要设置任何会创建层叠上下文的属性,并且让C的层级比E的高,这样的话,E自然会遮住B和D,而C又会遮住E,这就是我们要的效果。点这里看效果
不过在实际的项目环境中,D的transform属性一定会有(且其值会随表格的水平滚动条的拖动而改变),没法改变,所以在我看来这个问题似乎是无解的,只能采取一些替代方案。
这里要感谢我们前端组的同事water大神提供的三个替代方案:
- 让提示层往下移一点
- 把提示层改成浏览器默认的title
- 将提示层C放在D的外层,并控制其所在的位置
我采用了其中的第一种,因为这种方案体验还不错,并且实现起来比较简单。
第二种方案体验不太好,title属性的提示效果有点延迟,第三种方案实现成本太大了。
---------------------------------------- 2017-12-9 分割线 -----------------------------------------------
有很多开源组件使用了方案三,可以直接用,比如:Ant Design的Popover
---------------------------------------- 2017-12-9 分割线 -----------------------------------------------
最终的效果是这样的:
七、经验总结
这个问题本身是很简单的,之所以折腾了这么久,最主要的原因是之前没有深入去思考过z-index属性和层叠上下文(stacking context)的规则和原理,只是把问题解决了,而没有深入去思考:
- 为什么这么做可以?
- 背后的原理是什么?
- 有没有别的或者更好的方法?
现在这个问题也是一样,如果只是把提示层移下来完事,就不管这个问题了,也就不会深入去思考层叠上下文和z-index的相关知识和原理,这样永远无法真正的进步,无法成为领域的专家,永远只是大厦的建造者,而不是大厦的设计者。
从这个bug的修复过程中,我学到(领悟到)了以下三点经验:
1.关于z-index和层叠上下文原理相关的专业知识
- 层叠上下文(stacking context)并不只是z-index(必须配合position才能生效)才能创建,还有很多其他元素(如:opacity、transform等)也可以
创建层叠上下文
,不信点这里 - 在存在层叠上下文的情况下,z-index的大小决定了层叠水平(stacking level),即谁在谁上面,这是“
谁大谁上
”原则,不信点这里 - 层叠水平的比较只有在
同一级别的DOM节点的层叠上下文中才有意义
,就比如上面例子中的D和E比较是有意义的,但是C和E比较就没有意义了,因为如果D的层级比E小的话,C层级再大也没用,也不会在E之上,不信看这里 - 在同一DOM节点,并且层级水平一样的情况下,在HTML文档中写在后面的元素会遮住前面的元素(后者会在前者上面),这是“
后来居上
”原则,不信点这里
2.深入探索的精神
遇到问题,多思考:
- 问题是如何出现的?
- 为什么会出现?
- 涉及到哪一块的知识?
- 背后的原理是什么?
然后才是着手去解决:
- 先想方设法自己寻找解决方案
- 解决了回顾下这个问题,对这个问题进行抽象,看下有没有更好的解决方案
- 参考别人是如何解决这类问题的,别人的方法有什么优劣,并学习别人的闪光点,用微创新的方式,试着对现有的解决方案进行改良、优化、重构
3.解决问题的方法论
- 遇到问题,先分析这是个什么问题(如何分析?需要扎实的基础和丰富的实践经验),并根据自己的猜测去实验试错
- 自己解决不了,再自行Google/Baidu,并继续实验试错
- 还是解决不了,问导师、同事、朋友、网友(论坛、QQ群等)提供解决的思路(如何提问?点这里)
八、参考资料
会改变层叠上下文的情况:
翻译过来就是:
- 根元素
- position(值为"absolute"或"relative") + z-index(不为"auto")
- flex item(即父元素有"display:flex|inline-flex"属性的元素) + z-index(不为"auto")
- opacity小于1的元素
- transform不为"none"的元素
- mix-blend-mode不为"normal"的元素
- filter不为"none"的元素
- perspective不为"none"的元素
- isolation:isolate的元素
- position:fixed的元素
- 在will-change中指定了任意CSS属性,即便你没有直接指定这些属性的值
- -webkit-overflow-scrolling:touch的元素
[BUGCASE]层叠上下文和z-index属性使用不当引发的文本被遮挡的问题的更多相关文章
- z-index失效原因分析——由一个bug引发的对层叠上下文和z-index属性的深度思考
新年刚开工就被一个bug虐得整个人都不好了,特地记录下. (一)bug描述 在一个fixed-data-table(一个React组件)制作的表格中,需要给表头的字段提示的特效,所以做了一个提示层,但 ...
- 深入理解CSS中的层叠上下文和层叠顺序(转)
by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=5115 零.世间的道 ...
- 深入理解CSS中的层叠上下文和层叠顺序
零.世间的道理都是想通的 在这个世界上,凡事都有个先后顺序,凡物都有个论资排辈.比方说食堂排队打饭,对吧,讲求先到先得,总不可能一拥而上.再比如说话语权,老婆的话永远是对的,领导的话永远是对的. 在C ...
- [转]深入理解CSS中的层叠上下文和层叠顺序
http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/ 零.世间的道理都是 ...
- CSS中的层叠上下文和层叠顺序
一.什么是层叠上下文和层叠水平 层叠上下文和层叠水平有一点儿抽象.我们可以吧层叠上下问想象成一张桌子,如果有另一个桌子在他旁边,则代表了另一个层叠上下文. Stacking context 1由文件根 ...
- 关于css的层叠上下文和层叠顺序问题
关于css的层叠上下文和层叠样式问题 最近在项目中遇到了一个让我欲仙欲死的问题,我给项目中的图片设置了一个淡入效果,几opacity变化,但当我在它的上面有一个定位元素时,动画结束后,定位元素居然被遮 ...
- css 层叠上下文和层叠顺序
层叠上下文是css中的一个三维概念,拥有层叠上下文的元素在z轴上比普通元素要高,而且其内部的所有内容是自成体系的,其后代都是在它的层叠顺序中 哪些元素拥有层叠上下文 1.根元素,也就是html默认拥有 ...
- Elasticsearch学习之图解Elasticsearch中的_source、_all、store和index属性
转自 : https://blog.csdn.net/napoay/article/details/62233031 1. 概述 Elasticsearch中有几个关键属性容易混淆,很多人搞不清楚_s ...
- css之层叠上下文和层叠顺序
大家在写网页的时候会不会经常遇到莫名奇妙的样式问题,比如谁覆盖了谁.也找不出原因,为什么z-index高的却没有覆盖掉z-index低的元素呢? 带着这些疑问.我做了个小实验.代码如下: <st ...
随机推荐
- Java Web中解决乱码的方式
Java Web中解决乱码的方式 方式一:添加编码过滤器 package com.itmacy.dev.filter; import javax.servlet.*; import javax.ser ...
- [UOJ 275/BZOJ4737] 【清华集训2016】组合数问题 (LUCAS定理的运用+数位DP)
题面 传送门:UOJ Solution 这题的数位DP好蛋疼啊qwq 好吧,我们说回正题. 首先,我们先回忆一下LUCAS定理: \(C_n^m \equiv C_{n/p}^{m/p} \times ...
- [NOIP 2016D2T2/Luogu P1600] 天天爱跑步 (LCA+差分)
待填坑 Code //Luogu P1600 天天爱跑步 //Apr,4th,2018 //树上差分+LCA #include<iostream> #include<cstdio&g ...
- 公钥、私钥、SSL/TLS、会话密钥、DES【转载】
原文链接:https://www.cnblogs.com/thbCode/p/5829719.html 一,公钥私钥1,公钥和私钥成对出现2,公开的密钥叫公钥,只有自己知道的叫私钥3,用公钥加密的数据 ...
- 腾讯开源 APIJSON 连创五个第一
腾讯第一个码云推荐项目,// 其它最早创建的是 TencentOS-tiny(码云) 2019.8.23 腾讯第一个码云GVP项目,// 其它最早创建的是 TencentOS-tiny(码云) 201 ...
- 时间序列数据的定义,读取与指数平滑(Java)
应上头的要求,需要实现以下指数平滑进行资源调度负载的预测,那就是用我最喜欢的Java做一下吧. 引用<计量经济学导论>的一句话:时间序列数据区别于横截面数据的一个明显特点是,时间序列数据集 ...
- Spider_基础总结1_Request(get/post__url传参_headers_timeout)+Reponse
网络爬虫(一) 一.简介 1.robot协议(爬虫协议):这个协议告诉引擎哪些页面可以抓取,哪些不可以 -User-agent:爬虫引擎 -allow:允许robot访问的URL -disallow: ...
- Interface(接口分享)第一节
一.接口初探 有时候我们传入的参数可能会包含很多的属性,但是编译器只会检查那些必须的属性是否存在,以及类型是否匹配,而咱们要讲的接口其实就是用来描述下面这个例子里的结构,对于接口传入的数据咱们只关心它 ...
- Serilog 源码解析——数据的保存(上)
在上一篇中,我们主要研究了Serilog是如何解析字符串模板的,它只是单独对字符串模板的处理,对于日志记录时所附带的数据没有做任何的操作.在本篇中,我们着重研究日志数据的存储方式.(系列目录) 本篇所 ...
- 【JVM第二篇--类加载机制】类加载器与双亲委派模型
写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 一.什么是类加载器 在类加载过程中,加载阶段有一个动作是"通过一个类的全限 ...