聊聊css的z-index层级失效问题

这是我参与更文挑战的第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>
复制代码

这里是预期的场景;

image.png

这里是还原的,当滚动回顶部导致z-index失效之后的样式。

image.png

那么这里到底发生了什么了?

经过一顿搜索之后,代码修改如下:

.wrap{
    position: absolute;
    left: 0; right: 0;
    top: 0; bottom: 0;
    background-color: #fff;
    transform: translateY(0px);  /* 新增样式 */
}
复制代码

这里添加的transform。是下拉刷新的功能,要还原到顶部,否则下次下拉会直接偏移到上一次下拉的部分。

下拉刷新部分如下图红框。 松开之后需要通过transform: translateY(0px); 来还原

image.png

问题分析

在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世界太美妙,这里每天都会有各种各样的故事。

希望今天的文章能帮到大家吧。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享