CSS-合理使用z-index控制盒子視軸高度,解決z-index失效

寫在前面,如果你只關心正文請跳過這部分。我關於css的博客很少,首先是沒有什麼寫靜態頁面的需求,其次是css總是給我一種“不可控”的感覺。比如,我寫過仿知乎首頁的靜態頁面,當時完全不知道爲什麼這個塊“跑掉了”,就不停測試給跑掉的塊加各種樣式,“殺手鐗”就是absolute和z-index —— x軸、y軸位置不對我就調left、top值,z軸(視軸,或者說哪個塊在上面,可以直接看到)不對我就調z-index。結果用chrome一看,全是無效樣式,滿屏絕對定位、999的z-index,過程中我也是痛苦不堪。最近有需求寫幾個靜態頁面,就沉下心認真看了看css,今天分享的部分是如何合理使用z-index。

關於z-index我們的共識

共識一

首先,我們都同意,z-index對於普通盒子是無效的,這裏的“普通盒子”是除了下文我會提到的“神奇盒子”外的所有盒子,至於什麼是“神奇盒子”請慢慢看。
對於普通盒子,不管z-index值如何,寫在html文檔中後面的塊會在寫在前面的盒子上面,float的盒子會在沒有float的盒子上面,文字等inline、inline-block元素會在block元素的上面。

以下所有代碼示例請查看github查看完整源碼

    <div class="first">first div</div>
    <div class="second">second div</div>
    <div class="inline">inline div</div>
    <div class="float_first">first float div</div>
    <div class="float_second">second float div</div>
        div{
            width: 100px;
            height: 200px;
            border: 2px solid silver;
        }
        .first{
            background-color: blue;
        }
        .second{
            background-color: red;
        }
        .inline{
            display: inline-block;
            background-color: pink;
        }
        .float_first{
            float: left;
            background-color: green;
        }
        .float_second{
            float: left;
            background-color: orange;
        }

x軸、y軸位置我是在chrome中用margin-top負值和margin-left正值調的,結果如下:
這裏寫圖片描述
不管我如何給first div加z-index,哪怕給個9999這麼大值,second div還是在其上面,其他塊同理,z-index不能影響上圖視軸(z軸)順序,html標籤順序會影響first div、second div及first float div、second float div視軸高低。所以說,z-index不是給這些盒子使用的。

共識二

對於受z-index控制的,姑且稱之爲“神奇”的盒子(其實就是很多博客說的 stacking context,層疊上下文 ),z-index值越大其視軸越高,離用戶越近,最大的就在最上面,會遮擋其他神奇盒子。
這點不用我舉例吧,很多人都習慣寫z-index:900這種樣式,就是想讓這個盒子在最上面,當又出現一個盒子,就不得不寫z-index:901這種讓人迷糊的樣式。

兩個共識引出的一個問題

瞭解以上兩個共識以後,你有沒有想過這個問題,那麼z-index 負值 與 普通盒子們誰在上面呢?

神奇盒子(層疊上下文)與普通盒子的視軸排列

我首先想介紹下層疊上下文,也就是什麼樣的盒子是神奇的盒子。

具有哪些樣式的盒子會成爲神奇盒子(層疊上下文)

首先,我們最常見的定位不是static的盒子,是神奇盒子,其他創建神奇盒子的方式我引用的博客的總結,如下:

  • 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.
    關於以上總結,我測試過 opacity和transform ,但引用博客博主靠譜,大家可以親測下。其實,其他我沒測也是因爲不常用,大家有個印象就ok。

神奇盒子與普通盒子視軸高度

話不多說,上代碼。

    <div class="block">block box</div>
    <div class="absolute">absolute box</div>
    <div class="negative">negative box</div>
    <div class="positive">positive box</div>
    <div class="float">float box</div>
        html{
            padding: 200px;
        }
        div{
            width: 200px;
            height: 100px;
            border: 5px solid silver;
        }
        .block{
            background-color: green;
        }
        .absolute{
            position: absolute;
            background-color: blue;
            margin-top: -60px;
            margin-left: 40px;
        }
        .negative{
            position: absolute;
            background-color: red;
            z-index: -1;
            margin-top: -140px;
            margin-left: -20px;
        }
        .positive{
            position: absolute;
            background-color: purple;
            z-index: 1;
            margin-top: -40px;
            margin-left: 60px;
        }
        .float{
            float: left;
            background-color: pink;
            margin-top: -80px;
            margin-left: 20px;
        }

結果:
這裏寫圖片描述
結論: html -> z-index負值神奇盒子(絕對定位) -> 塊狀盒子 -> float 盒子 -> z-index auto或者0的神奇盒子(絕對定位) -> z-index正值神奇盒子(絕對定位),視軸越來越高。PS,inline或者inline-block盒子高於float盒子,但低於auto z-index神奇盒子,就是位於粉色和藍色盒子之間。

關於這個結論,你可以這麼考慮,在普通盒子視軸排列的基礎上,神奇盒子可以根據z-index值自由穿梭於普通盒子上或下。

以上都是兄弟盒子之間的關係,父子盒子關係很容易理解,子盒子會高於父盒子,不然我們寫的子塊不都被父塊覆蓋了。如果我想知道子盒子與其父盒子的兄弟盒子的關係呢(子盒子與其伯伯盒子的關係)?

當討論嵌套盒子視軸關係時需要注意的問題

這裏我只想提醒大家,如果父盒子是神奇盒子,子盒子與其伯伯盒子(子盒子的父盒子的兄弟盒子)的視軸關係是由父盒子與這個伯伯盒子關係決定的。比如:

    <div class="father">fahter box <div class="son">son box</div></div>
    <div class="brother">brother box</div>
        div{
            width: 200px;
            height: 100px;
            border: 5px solid silver;
            position: absolute;
        }
        .father{
            background-color: red;
            z-index: 0;
        }
        .brother{
            background-color: blue;
            z-index: 1;
        }
        .son{
            background-color: yellow;
            z-index: 999;
            width: 100px;
            height: 50px;
        }

位置請用margin或top、left自己在chrome裏調下,你會看到如下圖:
這裏寫圖片描述

沒錯,son的z-index爲999,但是居然不在最上面,最上面的是 z-index爲1的div。這個時候請不要大叫 z-index 失效,這是正常表現。因爲son的父盒子father是神奇盒子,它的z-index爲0,所以son與brother的關係由father與brother的關係決定,顯然father在下麼,那son就得在下,不管你給它設多大的z-index。

一道關於z-index的面試題

最後,既然你已經耐心讀到這了,我就給你出道題考考你。僅使用css如何讓上圖中的brother在son與father中間?也就是,僅使用css如何讓一個盒子位於它的兄弟盒子與兄弟盒子的子盒子中間。
如果你讀完了這篇博客,依然解決不了這個問題,可以留言,我悄悄告訴你答案。

發佈了82 篇原創文章 · 獲贊 82 · 訪問量 44萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章