[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 相对定位,原位置仍占用空间 ...
随机推荐
- [CQOI 2018]九连环
Description 题库链接 给你一个 \(n\) 连环,游戏规则是: 第一个(最右边)环任何时候都可以任意装上或卸下: 如果第 \(k\) 个环没有被卸下,且第 \(k\) 个环右边的所有环都被 ...
- wcf win7+iis7 异常消息为: 可能证书“CN=PmsWcfServer”没有能够进行密钥交换的私钥
原因是证书没有用户权限,解决方法: 1.开始-运行-mmc 2.添加[证书]管理单元 3.选择[证书(本地计算机)]-[个人]-[证书],右击PmsWcfServer证书-[所有任务]-[管理密钥] ...
- [转]数据库中Schema(模式)概念的理解
在学习数据库时,会遇到一个让人迷糊的Schema的概念.实际上,schema就是数据库对象的集合,这个集合包含了各种对象如:表.视图.存储过程.索引等. 如果把database看作是一个仓库,仓库很多 ...
- 简单的自定义Session
有关Session.Cookie机制建议参考文章:CookieSession机制详解,写的很详细,不再赘述 本篇文章通过一个简单的案例揭秘Session机制以及和Cookie的区别和联系: 服务器端代 ...
- Java中反射和Unsafe破坏单例设计模式
有如下单例模式设计代码: class Singleton { private String info = "HELLO SHIT"; private static Singleto ...
- 微信小程序,关于设置data里面的数据。
关于设置 data里面的数据 wxml: <view>{{userName}}</view> data: { userName:'张三', } 有两种方法 方法一:直接使用点关 ...
- 如何优雅的爬取 gzip 格式的页面并保存在本地(java实现)
1. 引言 在爬取汽车销量数据时需要爬取 html 保存在本地后再做分析,由于一些页面的 gzip 编码格式, 获取后要先解压缩,否则看到的是一片乱码.在网络上仔细搜索了下,终于在这里找到了一个优雅的 ...
- 【学习笔记】--- 老男孩学Python,day10, 初识函数 形参、实参
函数:对功能的封装语法: def 函数名(形参): 函数体 函数名(实参) 函数名:命名规则和变量一样 函数的返回值: return, 函数执行完毕. 不会执行后面逻辑 1. 如果函数中不写retur ...
- 一文告诉你git如何使用
提供简易教程学习网址 http://www.bootcss.com/p/git-guide/ git add . //提交至缓存 git commit -m '注释' //提交至本地 (git com ...
- PHP ServerPush (推送) 技术的探讨[整理]
需求: 我想做个会员站内通知的功能.不想用以前的ajax查询,听说有个推技术.以下文章介绍的不错,来自转载, ============================================= ...