[CSS]关于z-index与position的一次奇异经历
前言:
前不久,同事S遇到了一个关于position和z-index的问题。 他折腾了一天没搞定,群发了邮件寻求帮助, 我一开始以为很简单,就主动说帮忙,简单尝试之后,才发现貌似没那么简单。 问题主要围绕position和z-index。
问题:
我们项目用的是react,同事S有一个table,table里有row,这个table用了一个第三方component,具体什么component无所谓了,总之这些row都有一个css属性:
positon: absolute;
然后,在每个row中有个自定义的下拉框组件,下拉框点击后,会弹出一个选项的容器,他期望选项(options)的容器div(暂称div-options)在页面的顶层,也就是不会被其他东西遮盖。但是结果就是被当前row之后的row给遮盖了。div-options有如下css属性:
position: fixed;
问题的初始状态类似如下例子:
https://codepen.io/bee0060/pen/GGvMxb
在我的例子中,可以简单的对div-options添加大于0的z-index属性解决。 只是在我同事的本地,貌似仅仅这样无法解决,具体原因当时没有意识到所以也就没有细查。 不过我现在的猜测是,每个row上面都有z-index属性,类似如下例子:(没错,该例子中div-options会被后面的row遮盖)
https://codepen.io/bee0060/pen/PaVwvj
在发现只给div-options增加z-index无法解决问题后,我也尝试建议我同事给每个row增加一个z-index,而且值小于div-options的z-index, 但是div-options依然被后面的row遮盖。
当时我觉得真是不可思议,整个人都懵了。
后来试了几种办法没成功就下班回家了。 在下班路上我好想意识到了什么,就回家试了下,发现了以下两种解决方案:
1. 在所有row有z-ind"Wx的情况下, 给div-options所在的row一个较大的z-index值,这样div-options无需z-index也不会被遮盖 , https://codepen.io/bee0060/pen/eKepZG
2. 将div-options提取到table之外,让他们没有父子层级关系,再给一个较大的z-idnex也可以解决,https://codepen.io/bee0060/pen/yEozro
在当前项目环境下,考虑到我们用的是react,我建议我 同事采用第二个解决方案。因为在显示div-options时去修改所在row的z-index,这个操作要影响的对象太多了,而且会对上级(父级)组件造成影响,感觉不太好,要知道,影响的组件越多,就会触发越多的diff和re-render,所以我还是希望这个操作只需要通知尽可能少的组件就能完成。
问题是解决了,但是到底这问题是怎么引起的呢?
我查阅了一些资料, 下面的是我的一些分析和猜想,主要面向希望快速解决问题并获得一个大概思路的朋友。
如果需要更详细准确的解释,我需要查阅更多资料后另开一篇博客,或者你们可以看下其他更详细的博客,正好这就有一篇我感觉不错的。
好,那么下面我要开始表演了。
原因分析:
首先,有些废话还是要说。
我列一下关键的分析依据:
1. 只有已经定位的元素(即position属性值是非static的元素)的z-index属性会生效
2. 在同一堆叠中,z-index值大的遮盖 小的对象
3. 在同一堆叠中,若z-index值相同,后面的对象遮盖前面的对象。
4. z-index为数字(包括0)的元素会在当前堆叠上下文(暂称为堆叠A)中创建堆叠层级(暂称堆叠B),堆叠B可视为堆叠A的子级堆叠。
5. 一个对象只与处于相同堆叠上下文的对象进行z-index的比较并决定哪个遮盖哪个。
6. 若A 和B对象处于同一 堆叠上下文,且根据z-index规则已确定B显示在A上面,那么堆叠B及其所有子级堆叠都将显示在堆叠A以及堆叠A的子级堆叠之上。(因为子级堆叠的显示顺序无法超出父级堆叠的顺序,无论z-index的数值多大)
上面多次出现”堆叠“这个名词,堆叠可以理解为css空间中,延Z轴方向互相层叠的多个小空间。 很多博客在图例中把堆叠画得像一张纸一样,其实并不准确,因为堆叠中可以有子级堆叠,里面可以有无限个层级,所以我觉得理解为空间更合适。 可以理解成较扁平的空间。 而css空间(或你叫DOM或HTML空间也可以)中默认会创建一个堆叠。
看完上面几条,估计大家也有头绪了。 在css空间里,如果对象没有被定位(position不为static)或已定为但z-index不为数字, 那么该对象会被至于父级元素所在的堆叠之内,否则会在父级对象所在的堆叠中创建新的堆叠。 一般情况下,如果页面中全都是不会创建堆叠的对象(未定位或z-index不为数字),那么全部对象都将被置于默认堆叠内。
而每个堆叠内的子堆叠都无法超出其父堆叠的顺序进行显示,如果把堆叠理解成空间,这个应该比较好理解了。用修仙小说的话说就是:张三是某个世界里的人,他再牛也不能超出你所在的世界(当然一般修真小说写的都是能超出,你能理解我的话就好)。
那么结合之前遇到的问题就好理解了。
- 默认情况下,row只有position:absolute, 而都没有z-index时,他们都处于默认堆叠中,且按row的前后顺序进行遮盖, 而div-options属于某一个 row,按顺序的话,他顶多和他所在的row使用一个显示顺序,所以自然会被后面的row遮盖。
- 单独给div-options添加大于0的z-index后, div-options会在默认堆叠(即所有row所在的堆叠)上创建堆叠层级,且由于z-index大于0,在与处于同一父级堆叠中的所有row对象比较后,由于row都没有z-index,显示顺序和z-index为0时相同,所以div-options会显示所有在row之上,也就不会被遮盖了。
- 在给row都增加一个数字的z-index(即使是0)之后,后续的rows又会遮盖div-options。因为指定了数字z-index的row都会在父级堆叠中创建自己的堆叠,而div-options会在其父级row的堆叠内再创建堆叠。 而div-options的父级row(暂称rowP)只会与处于同一个父级堆叠的其他row的堆叠进行显示顺序比较, 所以后续row会显示在rowP之上。而div-options是rowP的堆叠的子堆叠,所以无论div-options的z-index多大,都无法超出rowP所在的堆叠。所以div-options会被后续rows遮盖。
所以我的两个解决办法就是从两方面 着手:
1. 给rowP更大的z-index,让其显示在所有兄弟rows之上,那么div-options无论有无z-index都不会被后续row遮盖。
2. 将div-options抽出来,不再作为rowP的子对象,也就不会再守rowP的堆叠顺序影响,进而可以实现让div-options不被后续row遮盖,因为div-options与所有rows可以处于同一个父级堆叠中,谁先谁后就只由他们各自的z-index值决定。
好了,分析思考和猜测就到这了,本来想尽量简短,但还是写了那么多。
最后说句最重要的: 如有谬误,欢迎指正!
后话:
在解决过程中,没在网上找到该问题的相关资料’ 我(虽然后来找到了),而且自己之前研究也不深,本着DRY原则,避免下次遇到又要花时间折腾,故写下此文。
参考资料:
2. 《CSS权威指南》
3. https://developer.mozilla.org/zh-CN/docs/Web/CSS/z-index
[CSS]关于z-index与position的一次奇异经历的更多相关文章
- CSS布局 ——从display,position, float属性谈起(转)
CSS布局 ——从display,position, float属性谈起 页面布局,或者是在页面上做些小效果的时候经常会用到 display,position和float 属性,如果对它们不是很了 ...
- CSS 浮动(float)与定位(position)
一.浮动 1.三个属性:left.right.none. 2.特点:容易造成父项塌陷,故在父项需要清除浮动 3.父项塌陷现象 4.父项塌陷解决方案(建议使用):清除浮动 .parent:after{ ...
- Html CSS学习(五)position定位 原
Html CSS学习(五)position定位 position用来对元素进行定位,其值有以下几种: static:无特殊定位,对象遵循正常文档流,top,right,bottom,left等属性不会 ...
- css中的定位属性position(转)
css中的定位属性position 同样的也是上课的时候发现学生难以理解的一些问题拿出来记录一下,希望帮助初学者. 在css中定位属性position的运用在页面中是很常用的,特别是一些结合js来 ...
- [转][译]关于CSS中的float和position和z-index
原文:http://learn.shayhowe.com/advanced-html-css/detailed-css-positioning 当构建页面排版时,有不同的方法可以使用.使用哪一种方法取 ...
- [译] 关于CSS中的float和position
原文 http://learn.shayhowe.com/advanced-html-css/detailed-css-positioning 当构建页面排版时,有不同的方法可以使用.使用哪一种方法取 ...
- CSS布局 ——从display,position, float属性谈起
页面布局,或者是在页面上做些小效果的时候经常会用到 display,position和float 属性,如果对它们不是很了解的话,很容易出现一些莫名其妙的效果,痛定思痛读了<CSS Master ...
- CSS布局学习笔记之position
CSS知识点 之 position布局 前段时间被同学怂恿,参加了百度前端技术学院的一个小培训,第一个阶段下来学到不少东西.课程的第一个阶段主要是HTML5 和 CSS 基础知识的一个小培训,给出的一 ...
- CSS中常见的位置(position)属性
常用的位置属性列表: position(top.bottom.left.right) .overflow.z-index position用法: 值 描述 relative 相对定位,原位置仍占用空间 ...
随机推荐
- AOE网与AOV网
因为有人无端怀疑此博客为抄袭, 且作者写作此博客时仅为应试之用,今毕业已久此文章已无用处 故删除文章,不想再无故受到打扰 祝好
- hadoop学习笔记(三):hadoop文件结构
hadoop完整安装目录结构: 比较重要的包有以下4个: src hadoop源码包.最核心的代码所在目录为core.hdfs和mapred,他们分别实现了hadoop最重要的3个模块:基础公共库.H ...
- 使用Python学习RabbitMQ消息队列
rabbitmq基本管理命令: 一步启动Erlang node和Rabbit应用:sudo rabbitmq-server 在后台启动Rabbit node:sudo rabbitmq-server ...
- 三种数据库访问——Spring3.2 + Hibernate4.2
前三篇随笔中介绍了 用原生的JDBC访问数据库.一种高效的数据库连接池druid.用Spring的JDBC框架访问数据库. 本文继续介绍第三种数据库访问的解决方案:Spring3.2 + Hibern ...
- c#读取html文件内容替换之后再写入
string sss = File.ReadAllText("E:\\FM\\Mall\\MallSGWeb\\MallSGWeb\\MALL_simple\\File\\11111.htm ...
- Angular建立待办事项应用
建立路由 接前一小节,在src/app/app.component.html把login组件去掉 第一步: 在src/index.html指定基准路径 浏览器会根据这个路径下载css,图像,js文件, ...
- Android Studio 3.0找不到Android Device Monitor
因为自Android Studio 3.0开始弃用Android Device Monitor,Android Developers官网上的原话是: Android Device Monitor is ...
- 关于ajaxFileUpload只能上传一次的解决
今天用ajaxFileUpload做了一个上传文件到服务器的功能. 出现问题:先上传了一次,后来发现读取完成以后,再上传的时候前台调试file和自动义参数都传进,但后台获取的仍然是上一次上传时的相关参 ...
- 为什么java需要序列化对象
序列化是一种用来处理对象流的机制 所谓对象流:就是将对象的内容进行流化,可以对流化后的对象进行读写操作,也可将流化后的对象传输与网络之间 序列化是为了解决在对象流进行读写操作时所引发的问题 序列化的实 ...
- 【基于初学者的SSH】struts2 值栈的详解与struts2标签库+ognl表达式
一:什么是值栈:struts2里面本身提供的一种存储机制,类似于域对象,值栈,可以存值和取值 特点:先进后出,最上面的元素叫做栈顶,也叫压栈. <s:debug></s:debug& ...