z-index和transform,你真的了解吗?
z-index
和transform
是CSS中的属性,但很少同学将二者联系到一起,感觉他们八杆子打不上。事实真的是这样吗?如果你也不能确认,这篇文章就值得你花点时间阅读。因为阅读完了,你会有所收获的。
堆叠上下文(Stacking Context)
在开始今天的主题之前,先得回忆一下CSS中的Stacking Context(堆叠上下文)。因为只有了解清楚了这个概念,才能更好的了解下面的内容。
任何HTML文档默认的堆叠上下文都是<html>
元素。因此,除非创建新的堆叠上下文。默认情况下,元素的堆叠顺序相对于页面内的其他元素。在一个未做堆叠顺序更换的页面中,其顺序就是根据HTML中的元素出现的先后顺序来决定,先出现的在底下,后出现的在顶部。用数字来表示的话是就1,2,3,4,...,n
这样的顺序。
第二个div
做了一个margin-top
的-50px
,可以看到第二个div
遮住了第一个div
。那么怎么才能改变默认的堆叠顺序呢?
先把结论给大家抛出来,在CSS中可以使用z-index
和transform
可以改变元素的堆叠顺序。但也可能会导致一些奇怪的情况,比如具有较大的z-index
的元素并不总是位于具有较低z-index
元素的上方。比如,在一些情况之下,同时使用z-index
和transform
会让z-index
失效等。
CSS中会产生新的层情况还有很多种:
当一个元素位于HTML文档的最外层(
<html>
元素)当一个元素被定位了并且拥有一个
z-index
值(不为auto
)当一个元素被设置了
opacity
,transforms
,filters
,css-regions
,paged media
等属性
flex item
,也就是父元素的display
设置了flex
或者inline-flex
值,早期的box
值不行
grid item
,也就是父元素的display
设置了grid
或者inline-grid
值
isolation:isolate
元素的
mix-blend-mode
值不为normal
元素的
overflow-scrolling
值不为touch
元素的
filter
值不为none
元素的
perspective
值不为none
元素的
motion-path
值不为none
三维空间
Web中的任何元素都存在于一个三维空间中,除了大家熟知的平面画布中的x
轴和y
轴之外,还有控制第三维度的z
轴,如下图所示:
在CSS中使用margin
,float
、offset
这些属性,可以控制元素在x
轴和y
轴上的表现。而z
轴上的表现形式可以通过z-index
和transform
来控制。
如何控制z轴
前面也说了,控制z
是通过z-index
和transform
来实现的。先简单的了解一下这两种控制z
轴的方法。
通过z-index
控制z
轴,需要配合position
属性,且position
的属性值为relative
、absolute
、fixed
和sticky
时。并且给z-index
显式的设置数值,数值越大,其层级越高。简单点说,数值越高,元素越在顶上。
transform
可以通过它的translateZ()
来改变元素的层叠顺序,其值越大,越在顶层,离屏幕越近。不过通过transform:translateZ()
改变元素z
轴的层级,必须在元素的父元素中显示的设置transform-style: preserve-3d
或者在transform
中显示的设置perspective()
。如下所示:
上面的示例可能还不能明显的说明translateZ()
改变堆叠上下文z
轴的顺序,因为上面的代码有position
设置,那你要是觉得好奇,可以看下面这个示例。
示例左边的元素是没有设置translateZ
,右边的元素设置了translateZ
。
有关于z-index
和transform
更多的教程可以阅读下面这些文章:
z-index 和 translate3d
特别声明:接下来的内容挑选于@凹凸实验室的《探究
transform
动画元素的z-index
》一文。此文章详细讲解了transform
和z-index
在一起使用将会发生的状况。
在一次需求中,需要做出三张卡牌走马灯式滚动的效果,由于在前面的一张卡牌需要挡住后面的卡牌,自然而然地就用 z-index
使前面的卡牌显示在最上面,配以 transform
动画让“走马灯”滚起来,在开发过程中,在 PC 侧 Chrome 中表现良好,在本人手机浏览器中也表现良好,最后测试时却发现,在微信客户端或 QQ 客户端中打开页面出现问题,“走马灯”滚动时,卡牌先通过transform
就位后,才把 z-index
设置较大的卡牌置于上面,感觉上非常的不流畅。
究其原因,发现这是某些浏览器的渲染规则,涉及到 stacking context 的概念,transform
的元素会创建新的 DOM,层级会在普通元素的上面,除了 transform
,还有哪些情况会创建新 stacking context呢?
下图是对 transform
和 opacity
的测试结果:
很明显,红色 div
都在绿色 div
上面了,说明真的有创建了个更高层级的 stacking context。再做进一步测试,我给两组的div
都加了 position:relative;z-index:1;
,结果绿色的都在上面了,手机微信上也一样,这能不能说明 z-index
对层级的影响大于 transform
和 opacity
呢。
至于 transform
变换的时候会让 z-index
“临时失效”,其实并非 z-index
失效了,只是 z-index
被用在不同的 stacking context 上,而非在默认的 context 上同等地比较层级了。所以 DOM 在 transform
的工程中,DOM 处于一个新的 stacking context 里,z-index
也是相对于这个 stacking context 的,所以表现出来的实际是 stacking context 的层次,动画一结束,DOM 又回到默认的 context 里,这时的 z-index
才是在同一个 context 上的比较。
那该用什么方法来控制卡牌的层级,又能让动画流畅地表现呢,当然是 translate3d
中的 z-axis
,很多时候我们并不知道它是用来做什么的,平常用得最多的只是它的 x-axis
和 y-axis
,不妨先看个例子:
实际效果是,看不到它们,然后我们再设置 perspective
为 201px
,这时可以很明显地看到,.box2
占据了整个屏幕,而.box1
宽高约为 200px
,唯有设置 translate3d(0,0,0)
时,宽高才为 100px
。
现在可以来理解下 perspective
和 translate3d
的关系,perspective
可以比作镜头和 DOM 的距离,实际上设置多少都没影响,因为它通过跟 z-axis
上的数值比例来影响样式,它更像是一个刻度,而 translate3d
的 z-axis
则表示了 DOM 和屏幕的距离。假定镜头跟屏幕的距离固定了,z-axis
越大,DOM 逐渐远离屏幕,靠近镜头,这时 DOM 看起来也就越大,当 z-axis
大于或等于 perspective
时,DOM元素已经在我们镜头的后面了,所以也就看不到它了。
现在也就好理解为什么 perspective
和 translate3d
能够影响 DOM 的层级了,它们在屏幕和镜头之间的距离不同,所以就有了层次,移动端设备很好地表现了这个结论,但在 PC 的 Chrome 上测试则不然,我们仍需要 z-index
才会表现出我们需要的 层次关系。
transform变换z-index层级渲染异常
在一些浏览器或设备上,当transform
和z-index
在一起使用时会发生异样,造成z-index
失灵。至于为什么会失灵,以及如何解决,这里就不多讲了。如果您对这方面的感兴趣,可以看看@张鑫旭大师写得一篇文章《Safari 3D transform变换z-index层级渲染异常的研究》。
文章总结了两种解决方案:
方法1:父级,任意父级,非
body
级别,设置overflow:hidden
可恢复和其他浏览器一样的渲染方法2:以毒攻毒。也可以使用3D transform变换
至于怎么使用3D Transform,大家还是移步看张大师是怎么分析的。
何时使用Transform来实现z-index
在介绍 z-index
和 translate3d
一节中,我们也了解到了,有时候设置z-index
来控制z
轴并不有效,张大师文章也提到过,它们在一起使用时,有时候会使用z-index
失灵。其实还有一个现象,大家可能平时并没有注意到。
当你通过z-index
配合伪元素::before
或者::after
时让其z
轴在元素的底部,特别是碰到大的元素渲染(比如全屏背景图),会直接影响性能,特别是在移动端,会造成客户端闪退,也就是大家所说的Crash,给用户造成非常不好的体验。
缩合上面的几个现象(当然可能还有很多我自己没有发现的),我们可以抛弃z-index
来控制z
轴的顺序,而是直接通过transform
中的translateZ()
或者translate3d()
来控制z
轴的顺序。
总结
单独使用z-index
或者transform
中的translateZ
、translate3d()
,或许你都不会想到他们之间有这么多的故事,甚至更没有想到在实际业务中通过transform
来替代z-index
来控制元素的z
轴的顺序。那么这篇文章介绍的就是这两者之间的故事,以及如何通过transform
来控制元素z
轴的顺序。如果文章讲解的有不对之处,或者你碰到过更奇葩的现象,以及相关的解决方案,欢迎在下面的评论中与我们一起分享。
z-index和transform,你真的了解吗?的更多相关文章
- 吃透css3之3d属性--perspective和transform
本文为原创,转载请注明出处: cnzt 写在前面:最近写了个3d轮播效果图,在此将思路和过程中遇到的问题都记录下来. 首先,我们下来了解一下perspective和transform都是做什么的. t ...
- CSS3的变形transform、过渡transition、动画animation学习
学习CSS3动画animation得先了解一些关于变形transform.过渡transition的知识 这些新属性大多在新版浏览器得到了支持,有些需要添加浏览器前缀(-webkit-.-moz-.- ...
- Animate与transform的使用
Animate是用css给前端加载动画的效果: 网址:https://daneden.github.io/animate.css/ <!DOCTYPE html> <html lan ...
- SQL Server中LIKE %search_string% 走索引查找(Index Seek)浅析
在SQL Server的SQL优化过程中,如果遇到WHERE条件中包含LIKE '%search_string%'是一件非常头痛的事情.这种情况下,一般要修改业务逻辑或改写SQL才能解决SQL执行 ...
- Transform.Translate 平移
function Translate (translation : Vector3, relativeTo : Space = Space.Self) : void Description描述 Mov ...
- Unity Transform常识(转)
Variables position: Vector3 物体在世界坐标中的位置. transform.position=Vector3(10,10,10)//把物体放到(x=10,y=10,z= ...
- CSS3总结七:变换(transform)
2D视图模型解析 3D视图模型解析 平移 旋转 伸缩 扭曲 z轴方向平移与perspective的神秘关系 matrix()终极变幻的方法 一.2D视图 2D视图就是默认平面上的每个点都与视线垂直,图 ...
- # Unity 游戏框架搭建 2019 (十六、十七) localPosition 简化与Transform 重置
在上一篇我们收集了一个 屏幕分辨率检测的一个小工具.今天呢再往下接着探索. 问题 我们今天在接着探索.不管是写 UI 还是写 GamePlay,多多少少都需要操作 Transform. 而在笔者刚接触 ...
- [转]unity3d 脚本参考-技术文档
unity3d 脚本参考-技术文档 核心提示:一.脚本概览这是一个关于Unity内部脚本如何工作的简单概览.Unity内部的脚本,是通过附加自定义脚本对象到游戏物体组成的.在脚本对象内部不同志的函数被 ...
随机推荐
- 使用redis-py的两个类Redis和StrictRedis时遇到的坑
使用redis-py的两个类Redis和StrictRedis时遇到的坑 前言: 今天产品经理说,有几个队列排序的功能不能用了.对比了下以前的代码查到了一个原因,这个比较的坑,总结起来也是自己没好好看 ...
- springboot之docker化
1.Docker安装 本人是centos7系统,安装也是按照官方文档进行安装.https://docs.docker.com/install/linux/docker-ce/centos/ ,即 1. ...
- SpringCloud学习成长之路二 服务客户端(rest+ribbon)
在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的. Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是f ...
- Web聊天室的实现
Tornado普通方式实现聊天室 普通的http方式连接的话,基本思路是前端页面通过JS重复连接后端服务器. 核心文件:app.py #!/usr/bin/env python # -*- codin ...
- 获取src 内容
获取(代码): ].src; // 测试无效 修改(代码): 1 $("#img").attr('src',path);
- MS SQL查询所有表行数,获取所有数据库名,表名,字段名
1.获取所有数据库名 --SELECT Name FROM Master..SysDatabases ORDER BY Name -- 2.获取所有表名: --SELECT Name NAMEtemp ...
- 极客时间-左耳听风-程序员攻略-UI/UX设计
程序员练级攻略:UI/UX设计 学习设计新手, 7 steps to become a UI/UX designer 学习设计的一些原则和套路,如配色.平衡.排版.一致性等. 用户体验的 4D 步骤- ...
- react做的react-redux购物车
### 1. 创建项目 create - react - app 项目名(shop) ### 2. 进入项目,下载redux,react-redux cnpm install redux ...
- 【数据库开发】windows环境下通过c++使用redis
1.Windows下Redis的安装使用 Redis是一个key-value存储系统.Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起 ...
- mysql 1366错误