CSS理解之z-index

作者: 徐国军_plus | 来源:发表于2017-08-02 18:50 被阅读195次

    1.z-index基础

    z-index属性指定了元素及其子元素的[z顺序],而[z顺序]可以决定
    当元素发生覆盖的时候,哪个元素在上面。通常一个较大z-index值的元素会覆盖较低的那一个。

    z-index支持的属性值:

    1. z-index:auto;默认值,如果不对z-index设置,默认为auto;
    2. z-index:<integer>;整数值,z-index:1,z-index:2等
    3. z-index:inherit;继承
    

    z-index基本特性:

    1. 支持负值;
    2. 支持CSS3  animation动画;
    3. 在CSS2.1时代,不考虑CSS3,z-index要起作用需要和定位元素配合使用,只有定位元素(position:relative/absolute/fix/sticky)设置z-index才有作用(CSS3中有例外);
    

    2. z-index与定位元素

    如果定位元素发生了覆盖,且没有嵌套(不是一个定位元素里面嵌套着另一个定位元素),谁在上面遵守下面两个准则:

    1. 后来居上的准则,后面的覆盖前面的;
    2. z-index哪个大,哪个上;
    

    demo 1:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .div1 img{
                position: absolute;
            }
            .div2 img{
                position: relative;
                margin-left: 100px;
            }
        </style>
    </head>
    <body>
        <div class="div1">
            ![](a.jpg)
        </div>
        <div class="div2">
            ![](b.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png

    后面的定位元素覆盖前面的定位元素在上面渲染。

    demo 2:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .div1 img{
                position: absolute;
                z-index:2;
            }
            .div2 img{
                position: relative;
                z-index:1;
                margin-left: 100px;
            }
        </style>
    </head>
    <body>
        <div class="div1">
            ![](a.jpg)
        </div>
        <div class="div2">
            ![](b.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png

    z-index值大的在上面覆盖z-index值小的

    另一种情况:定位元素z-index发生了嵌套,谁在上面遵循如下原则:

    1. 祖先优先原则;
      demo :
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .div1 img{
                position: absolute;
                z-index:3;
            }
            .div2 img{
                position: relative;
                z-index:-1;
                margin-left: 100px;
            }
        </style>
    </head>
    <body>
        <div class="div1" style="position: relative;z-index: 1;">
            ![](a.jpg)
        </div>
        <div class="div2" style="position: relative;z-index: 3;">
            ![](b.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png

    可以看到嵌套了的z-index定位元素,尽管前面的子元素的z-index值大,还是后面的图片覆盖了前面的,这里就遵循了祖先优先原则。

    前提:祖先的z-index值是数值不是auto

    demo :

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .div1 img{
                position: absolute;
                z-index:2;
            }
            .div2 img{
                position: relative;
                z-index:1;
                margin-left: 100px;
            }
        </style>
    </head>
    <body>
        <div class="div1" style="position: relative;z-index: auto;">
            ![](a.jpg)
        </div>
        <div class="div2" style="position: relative;z-index:1;">
            ![](b.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png

    当第一个图片元素的祖先元素z-index值为auto时,祖先优先原则就会失效,z-index:auto可以看成是z-index:0,尽管第二个图片元素的祖先元素z-index值比0大,但还是第一个图片覆盖第二个图片。
    CSS2.1:(z-index:auto时)当前层叠上下文的生成盒子层叠水平是0。盒子(除非是根元素)不会创建一个新的层叠上下文。这是起作用的反而是子元素的z-index值。第一个子元素的z-index大于第二个子元素的,所以会覆盖。

    3.CSS中层叠上下文和层叠水平

    层叠上下文(stacking content)是HTML元素中的一个三维概念,表示元素在z轴上有了“高人一等”。

    页面根元素天生具有层叠上下文,称之为"根层叠上下文"

    z-index值为数值的定位元素也具有层叠上下文

    层叠上下文中的每个元素都有一个层叠水平(stacking level),决定了同一个层叠上下文中元素在z轴上的显示顺序。几乎所有的元素都有层叠水平,但是要放在层叠上下文中来看。

    层叠水平和z-index不是一个东西。普通元素也有层叠水平,但z-index只在定位元素上起作用。

    同一个层叠上下文中的层叠元素遵循“后来居上”“谁大谁上”的层叠原则。

    层叠上下文几个特性:

    • 层叠上下文可以嵌套(父元素中嵌套子元素),组成一个分层次的层叠上下文。
    • 每个层叠上下文和兄弟元素独立:当进行层叠变化或渲染的时候,只需要考虑后代元素
    • 每个层叠上下文是自成体系的:当元素的内容被层叠后,整个元素被认为是在父层的层叠顺序中

    4.理解元素的层叠顺序(stacking order)

    层叠顺序:元素发生层叠时候有着特定的垂直显示顺序。

    著名的7阶层叠水平(stacking level),用来判断元素发生层叠时谁在上谁在下:

    Paste_Image.png

    层叠元素的意义:

    规范元素重叠时候的呈现规则。
    

    为何层叠顺序是上面图片中的样子?比如:为何内联元素会覆盖浮动元素?

    之所以是这样的七阶,是因为这样更符合加载的功能和视觉呈现

    一般来说,像background/border是用来装饰的,块状元素、浮动元素都是用来布局的,而内联元素绝大部分是内容:图片、文字,因为内容是页面最重要的部分,因此层叠必须水平要高,重要的东西越要往上面放!

    demo :

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
           img{
            float: left;
            margin-right: -40px;
            width: 250px;
            height: 400px;
           }
        </style>
    </head>
    <body>
            ![](b.jpg)
            <span>
                以前浮动课学过,浮动设计的作用是实现文字环绕图片的效果。如果文字和
                图片发生重叠,显然,是后面的文字要优先显示的,因为,文字比图片重要。
            </span>
    </body>
    </html>
    

    这里把图片变成了浮动元素,内容(内联元素)覆盖了图片浮动元素,比浮动元素的层叠水平要高。

    Paste_Image.png

    demo:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
           .inline-block,.block{
               width: 400px;
               height: 200px;
               position: relative;
           }
           .inline-block{
               display: inline-block;
               background-color: olive;
               margin: -30px; 
           }
           .block{
               display: block;
               background-color: green;
           }
        </style>
    </head>
    <body>
        <div class="inline-block">
            display:inline-block
        </div>
        <div class="block">
            display:block;
        </div>
    </body>
    </html>
    
    Paste_Image.png

    内联元素比块状元素的层叠水平高,上面的背景色覆盖了下面的,但是下面的文字覆盖了上面的背景色。这是因为:背景色的覆盖是层叠顺序,文字的覆盖是后来居上原则。文字是inline元素和inline-block是平级的,所以这里要用到后来居上原则

    5.z-index与层叠上下文(解释z-index的实际行为表现)

    三个行为要点:

    1. 定位元素默认的`z-index:auto`可以看成是z-index:0
    2.z-index不为auto的定位元素会创建层叠上下文;
    3.z-index层叠顺序的比较止步于父级层叠上下文;
    

    第一个行为要点:定位元素默认的z-index:auto可以看成是z-index:0;

    demo 1:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
           
           .img1,.img2{
                width: 200px;
                height: 400px;
           }
           .img1{
    
           }
           .img2{
               margin-left: -60px;
           }
        </style>
    </head>
    <body>
        ![](a.jpg)
        ![](b.jpg)
    </body>
    </html>
    
    Paste_Image.png

    根据后来居上原则后面的元素会覆盖前面的元素

    demo 2:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
           
           .img1,.img2{
                width: 200px;
                height: 400px;
           }
           .img1{
                position: relative;
           }
           .img2{
               margin-left: -60px;
           }
        </style>
    </head>
    <body>
        ![](a.jpg)
        ![](b.jpg)
    </body>
    </html>
    
    Paste_Image.png

    第一个图片变成定位元素之后,前面的图片又覆盖了后面的,这是因为当变为定位元素后,没有对z-index设置值,所以默认值为auto,从层叠顺序上看,这时可以把z-index:auto看成是z-index:0。这时再对照七阶层叠那个图:

    Paste_Image.png

    第二个行为要点:z-index不为auto的定位元素会创建层叠上下文

    demo:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .div2{
                position: absolute;
                background: blue;
                width: 200px;
                height: 400px;
                margin-left: 100px;
            }
            .div2 img{
                position: relative;   
                margin-left: -100px;
                z-index: -1;
            }
        </style>
    </head>
    <body>
       
        <div class="div2">
            ![](a.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png

    绝对定位元素只是一个普通元素,并不具有层叠上下文。此时图片的层叠上下文是页面根元素。所以背景色会覆盖图片。

    一旦给父元素z-index值为数值不为auto时,

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .div2{
                position: absolute;
                background: blue;
                width: 200px;
                height: 400px;
                margin-left: 100px;
                z-index: 0;
            }
            .div2 img{
                position: relative;   
                margin-left: -100px;
                z-index: -1;
            }
        </style>
    </head>
    <body>
       
        <div class="div2">
            ![](a.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png
    当我们给父元素.div设置z-index:0;时,就创建了层叠上下文,此时图片的层叠上下为文就变成了容器。z-index负值的层叠顺序在层叠上下文元素的背景色之上。 Paste_Image.png

    从层叠顺序上讲,z-index:auto可以看成z-index:0。但是从层叠上下文来讲,两者却有着本质差异!本质差异:z-index:auto不可以创建层叠上下文,z-index:0可以。

    第三个行为要点:z-index受限于层叠上下文

    demo:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
           
           .img1,.img2{
                width: 200px;
                height: 400px;
           }
           .box1{
             position: relative;
             z-index: 0;
           }
           .box1 img{
              position: absolute;
              z-index: 99999;
           }
           .box2{
              position: relative;
              z-index: 1;
              margin-left: 120px;
           }
           .box2 img{
              position: absolute;
              z-index: -1;
           }
        </style>
    </head>
    <body>
        <div class="box1">
            ![](a.jpg)
        </div>
        <div class="box2">
            ![](b.jpg)
        </div> 
    </body>
    </html>
    
    Paste_Image.png

    可以看到尽管第一个图片的z-index远远大于第二个图片,但是由于第二个图片的父元素的层叠顺序大于第一个图片父元素的层叠顺序,所以最终的行为表现仍然是后面的覆盖前面的。

    6.其他CSS属性与层叠上下文(不只是z-index)

    1.页面根元素天生具有层叠上下文,称之为"根层叠上下文"。
    2.z-index值为数值的定位元素(相对或绝对)也具有层叠上下文。
    3.其他属性......创建层叠上下文。

    Paste_Image.png

    demo 1:display:flex与层叠上下文

    <!DOCTYPE html>
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <title>Document</title>
       <style>
           .box{
               background: blue;
               width: 300px;
               height: 500px;
               margin: 0 auto;
           }
           .box>div{
               z-index: 1;
           }
           .box>div>img{
               position: relative;
               z-index: -1;
               margin-left: -100px;
           }
       </style>
    </head>
    <body>
       <div class="box">
           <div>
               ![](a.jpg)
           </div>
       </div>
    </body>
    </html>
    
    Paste_Image.png
    由于.box不是层叠上下文元素,所以图片没有覆盖背景色,此时图片的层叠上下文为根元素。

    当我们为.box设置display:flex之后:

    Paste_Image.png

    图片覆盖了背景色。

    注意:给.box设置display:flex不是.box变为了层叠上下文元素,而是它的子项变成了层叠上下文元素

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .box{
                background: blue;
                width: 300px;
                height: 500px;
                margin: 0 auto;
                display: flex;
            }
            .box>div{
                z-index: auto;
            }
            .box>div>img{
                position: relative;
                z-index: -1;
                margin-left: -100px;
            }
        </style>
    </head>
    <body>
        <div class="box">
            <div>
                ![](a.jpg)
            </div>
        </div>
    </body>
    </html
    
    Paste_Image.png
    当对它的子元素的z-index值设置.box>div{ z-index: auto; }后,.box元素的子项就不再是层叠上下文元素了

    demo 2 :opacity ≠ 1 与层叠上下文

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .box{
                background: blue;
                width: 300px;
                height: 500px;
                margin: 0 auto;
            }
            .box img{
                position: relative;
                z-index: -1;
                margin-left: -100px;
            }
        </style>
    </head>
    <body>
        <div class="box">
            ![](a.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png
    当我们为.box元素设置opacity为0.5时: Paste_Image.png
    图片显示在了背景色上面,这是因为opacity ≠ 1的元素为层叠上下文元素。

    demo 3 :transform ≠ none 与层叠上下文

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .box{
                background: blue;
                width: 300px;
                height: 500px;
                margin: 0 auto;
                transform: rotate(15deg);
            }
            .box img{
                position: relative;
                z-index: -1;
                margin-left: -100px;
            }
        </style>
    </head>
    <body>
        <div class="box">
            ![](a.jpg)
        </div>
    </body>
    </html>
    
    Paste_Image.png
    transform ≠ none的元素为层叠上下文元素.

    ......以上不过多赘述。

    7.z-index与其它CSS属性层叠上下文(非定位元素层叠上下文和z-index关系)

    1.不支持z-index的层叠上下文元素的层叠顺序均是z-index:auto级别(不支持z-index的层叠上下文,指的就是那些CSS属性创建的层叠上下文)。

    Paste_Image.png

    举个例子:

    Paste_Image.png

    上图中img1、img2、img3、img4、img5依次相互覆盖,img1对应七阶层叠水平中的第五阶,是inline水平元素,img2、img4、img5是不依赖z-index的层叠上下文,img3是z-index:auto,它们都对应第六阶,属于同阶,遵循后来居上原则,依次覆盖。

    2.依赖z-index的层叠上下文元素的层叠顺序取决于z-index值

         依赖z-index值创建层叠上下文的情况:

    1.position值为relative/absolute或fixed(部分浏览器);
    2.display:flex|inline-flex容器的子flex项;

    Paste_Image.png Paste_Image.png

    上图中的.box元素是普通元素,它的子项才是层叠上下文元素,所以不仅被第一张图片覆盖,还被父元素的背景色覆盖

    Paste_Image.png
    Paste_Image.png

    相关文章

      网友评论

      本文标题:CSS理解之z-index

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