这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
需求背景
- 游戏界面有按钮浮层,浮层层级高于游戏画面层级,按钮可点击;
- 游戏界面可切换横竖屏,竖屏使用CSS3属性——
transform:rotate(-90deg);方法旋转游戏画面。
bug描述
游戏在竖屏模式下,视频开关按钮显示不完整,且无法点击;游戏在横屏模式下,视频开关按钮显示完整,且可正常点击。
第一轮问题分析
小白:也就是横屏没问题,竖屏有问题?
小白:“按钮显示不完整且无法点击”?可能是层级问题,层级问题好解决啊,加个z-index试试,z-index:9999;
小白:???咦,怎么没生效?再大一点!z-index:9999999999;
第二轮问题分析
小白:横竖屏的区别只是在于屏幕旋转,所以问题可能出在transform:rotate(-90deg)方法上。
设置transform会产生什么影响?
- 给DOM设置
transform属性会创建一个新的stacking context(层叠上下文),使得原本的层叠规则发生变化,导致了设置了transform的元素变成了一个层叠上下文容器,层叠上下文容器的堆叠水平比普通元素高。这也就是为什么原本层级比较高的按钮会被遮挡住的原因。 - 给一个元素加上
transform效果后,它的子元素的z-index就“失效了”;其实并非z-index失效了只是z-index被用在不同的stacking context上;DOM在设置transform属性后,会处于一个新的stacking context里,z-index也是相对于这个stacking context的,所以这个时候无限加大z-index的值并不会达到预期效果。
解决办法
使用transform的translateZ(*z*)方法,在旋转的同时,设置其Z轴属性为0——transform:"rotate(-90deg) translateZ(0);将其所在的层叠上下文又会回到原来的位置,此时游戏画面层级不会覆盖按钮层级,问题完美解决。
相关知识背景
stacking context(层叠上下文)
堆叠上下文是HTML元素的三维概念,这些HTML元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的 z 轴上延伸,HTML 元素依据其自身属性按照优先级顺序占用层叠上下文的空间。
如何触发元素的堆叠上下文
根堆叠上下文(我们所有的元素排序都是在此上下文中进行的)
z-index值为数值的定位元素的传统堆叠上下文
CSS属性引起的
z-index值不为auto的flex项(父元素display:flex|inline-flex)
元素的opacity值不是1
元素的transform值不是none
元素mix-blend-mode值不是normal
元素的filter值不是none
元素的isolation值是isolate
will-change指定的属性值为上面任意一个
元素的-webkit-overflow-scrolling设为touch