这是我参与更文挑战的第19天,活动详情查看: 更文挑战
背景
作为一名初级前端、资深bug制造师、入门级bug修复师,今天又在公司的项目里发现了一个bug,打算解决了再记录下来的。
可这不巧了,刚好解决了。
css世界真奇妙啊。
先说说业务场景;
是用uni-app开发的一个app兼容H5,我新进公司,正在学习公司项目。
刚好看到一个bug,下拉刷新是自开发,没用uniapp的,项目中有一个引导界面。
但是在用鼠标滚动的时候,会出现引导层的z-index失效,怎么调整都没用。
于是开是探寻之路。
找到原因。
当时在看到这个bug的时候,我用力的观察着,想找到问题出现的时机。
终于,在多次尝试之后,确认问题是在滚动回顶部的时候出现的。
那么肯定是监听了滚动时间,并且在滚动回顶部的时候,做了什么操作,才导致的问题出现。
于是,顺着代码,找到了下拉刷新的组件,终于理清了问题的来龙去脉。
还原场景。
<body>
<div class="wrap">
<div class="guide"></div>
</div>
<div class="mask"></div>
</body>
<style>
body{ margin: 0; padding: 0; }
.wrap{
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
background-color: #fff;
}
.guide{
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
margin: auto;
width: 100px;
height: 100px;
background-color: red;
z-index: 99;
}
.mask{
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
margin: auto;
background-color: rgba(33,33,33, .3);
}
</style>
复制代码
这里是预期的场景;
这里是还原的,当滚动回顶部导致z-index失效之后的样式。
那么这里到底发生了什么了?
经过一顿搜索之后,代码修改如下:
.wrap{
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
background-color: #fff;
transform: translateY(0px); /* 新增样式 */
}
复制代码
这里添加的transform。是下拉刷新的功能,要还原到顶部,否则下次下拉会直接偏移到上一次下拉的部分。
下拉刷新部分如下图红框。 松开之后需要通过transform: translateY(0px); 来还原
问题分析
在css中,z-index是同级比较,通常我们会通过position的非static(默认值),之后设置z-index来调整层级。
而在设置transform之后,会触发元素的Stacking Context(堆叠上下文,css的三维概念)。继而重新渲染的元素的层级;
现在,已经定位了问题了,开始解决问题。
解决方法。
技术性的解决方法。
这种解决方法解决不了我的代码问题,但是也是一种思路。所以另写一套代码;
在共通父级设置transform-style: preserve-3d;,之后子元素都将按照三维的概念来渲染。
<body>
<!-- 添加一个非body的共通父级 -->
<div class="father">
<div class="wrap">
</div>
<div class="guide">guide</div>
<div class="mask">遮罩</div>
</div>
</body>
<style>
.father{
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
transform-style: preserve-3d;
}
.guide{ transform: translateZ(11px); }
.mask{ transform: translateZ(10px); }
</style>
复制代码
以暴制暴
在我的代码中, guide是wrap是子级,而mask是公用元素,所以需要分开,而wrap设置了transform之后,导致的整个wrap层级都低了下去。所以用这种方式无法解决,于是我做了一个很暴力,很歪门邪路的解法。
首先是uni-app的项目,所以.wrap这一块我是用v-if来渲染的。
<div class="wrap" v-if="showGuide" id="guideWrap">
<div class="guide"></div>
</div>
复制代码
而这时候我就通过判断guideWrap元素是否存在,如果存在的话,就将wrap的transform属性设置为空,取消掉这个属性,让他不触发Stacking Context。
总结
css世界太美妙,这里每天都会有各种各样的故事。
希望今天的文章能帮到大家吧。