美文网首页
当 fixed 定位遇上 z-index 时

当 fixed 定位遇上 z-index 时

作者: XiaoWhite | 来源:发表于2021-07-29 21:51 被阅读0次

    你是否碰到过这种情况:两个 div 都是 fixed 定位,但 z-index 值小的反而可以盖在 z-index 值大的上面。

    position:fixed 和 z-index

    首先明确以下两个属性:
    1、position:fixed; 根据 MDN 文档上的说法

    fixed元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transform, perspectivefilter 属性非 none 时,容器由视口改为该祖先。

    2、z-index 只在定位元素上有效,即 position 的值不为 static 时,而且 z-index 的值越大,元素的位置越靠前。

    参考链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/z-index

    所以当我们在一个 div 上使用 position:fixed 时,只要把 z-index 的值设置得越大,显示出来时就越靠前(不被遮挡)。
    以上就是我在此之前的理解。

    不一样的情况出现了

    今天碰到了这种情况,两个 div 都是 fixed 定位,但是一个 z-index:21; 的元素,把一个 z-index:1001; 的元素给挡住了。

    代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    
        <style>
            .a {
                width: 100vw;
                height: 100vh;
            }
    
            .b {
                position: relative;
                z-index: 20;
                width: 100%;
                height: 70%;
                background-color: antiquewhite;
            }
    
            .c {
                position: fixed;
                z-index: 1001;
                left: 30%;
                top: 30%;
                width: 30%;
                height: 30%;
                background-color: aquamarine;
            }
    
            .d {
                position: fixed;
                z-index: 21;
                width: 30%;
                height: 30%;
                left: 40%;
                top: 40%;
                background-color: red;
            }
        </style>
    </head>
    <body>
        <div class="a">
            <div class="b">
                b ---- z-index: 20;
                <div class="c">c ---- z-index: 1001;</div>
            </div>
        </div>
    
        <div class="d">d ---- z-index: 21;</div>
    </body>
    </html>
    

    效果:

    a 包含 b,b 包含 c,而 d 与 a 同级,c 和 d 都设置 position: fixed; 其中 c 的 z-index 为1001,而 d 的 z-index 为21,原本期望的结果是 c 在 d 的上面,如下图所示:

    image1.png

    实际运行出来的结果是 d 在 c 的上面。

    image2.png

    分析原因

    经过分析,问题出在 b 上面,在 b 上面设置了属性 position: relative;z-index: 20; ,当设置了这两个属性之后,在 b 上面就会创建一个层叠上下文,而 c 又是 b 的子元素,所以即使在 c 上面设置 z-index:1001;,它也只是在 b 以内有效,超出 b 元素范围后,c 的 z-index 值是没有意义的;
    b 元素的 z-index 值为20,它的参考对象是根元素 <html>,d 的 z-index 值为21,参考对象也是根元素 <html>,所以 d 会覆盖在 b 上面,而 c 又是 b 的子元素,无法突破 b,所以 c 也只能被 d 覆盖。

    层叠上下文

    产生上面这个问题的根本原因就是层叠上下文,所以弄清楚层叠上下文才是关键,请先仔细阅读 MDN 上的文档:层叠上下文

    在我们使用 z-index 属性时,一定要考虑层叠上下文,要清楚当前元素设置 z-index 之后,究竟是在哪个层叠上下文中起作用的,换句话说就是以哪个元素作参考的。

    产生层叠上下文的条件有十几种,文档中的元素只要满足其中一个,就会在当前元素(起名叫 father)上形成层叠上下文,而 father 元素的所有子元素,如果设置了 z-index ,它们在渲染时,参考的就是 father 元素,谁的 z-index 值大,谁就在前面,但即使给这些子元素设置的 z-index 值再高,当超出 father 元素之后,他们的 z-index 就没有用了,因为这些子元素和其它元素已经不在一个层级上了。至于能不能显示在前面,就要看 father 元素的 z-index 了。

    可以拿中国的省、地级市、直辖市来类比:
    重庆是一个直辖市,在行政地位与江苏省同级,而苏州只是江苏省下面的一个地级市,假如苏州市2020年的GDP超过了重庆市(都是假如,不要抬杠),在江苏省内开会的时候,苏州可以排在最前面,但是如果开全国性的会议时,重庆可以和江苏省坐一排,而苏州只能坐在后面,因为级别不同。
    这里全国就好比是 <html> 根元素,江苏省是一个层叠上下文,重庆也是一个上下文,GDP 就像是 z-index 值。江苏省和重庆在同一个层级中,都是省级行政单位,而苏州只是江苏省这个层叠上下文中的一个子元素,即使苏州的 GDP 超过了重庆,也还是一个地级市。

    搞清楚层叠上下文,在安排元素显示层级时特别有用,还能避免一起意料之外的情况发生,你就能明白,为什么 Element-UI 中有些组件,比如 Dialog、Drawer 这类弹框组件,会有一个 append-to-body 属性来解决层级问题。

    相关文章

      网友评论

          本文标题:当 fixed 定位遇上 z-index 时

          本文链接:https://www.haomeiwen.com/subject/vpbfvltx.html