關於z-index那些事

關於z-index的真正問題是,不多有人理解它究竟是怎麼用。其實它並不複雜,可是若是你歷來沒有花必定時間去看具體的z-index相關文檔,那麼你極可能會忽略一些重要的信息。html

例子

在接下來的HTML裏 有三個<div>元素,而且每一個<div>裏包含一個<span>元素。每一個<span>被分別給定一個背景顏色:紅、綠、藍。每一個<span>被放置到文檔的左上角附近,部分重疊着其餘 的<span>元素,這樣你就能夠看到哪些是被堆疊在前面。第一個<span>有一個z-index的值爲1,而其餘兩個沒有任 何z-index值。spa

代碼:code

span{ 
            position: absolute; 
            display: block; 
            height: 100px; 
            width: 100px; 
        } 
        .red{ 
            background-color: red; 
            z-index: 1 
        } 
        .green{ 
            top: 40px; 
            left: 40px; 
            background-color: green; 
        } 
        .blue{ 
            top: 80px; 
            left: 80px; 
            background-color: blue; 
        }

    <div> 
        <span class="red"></span> 
    </div> 
    <div> 
        <span class="green"></span> 
    </div> 
    <div> 
        <span class="blue"></span> 
    </div>

 

image

 

那問題來了,如何將紅色span元素堆在藍色和綠色後面,不要打破如下規則:

  • 不要以任何方式改變HTML標記。htm

  • 不要添加/修改任何元素的z-index屬性。blog

  • 不要添加/修改任何元素的position屬性。排序

若是你找到了答案,那麼它應該像下面這樣ci

div:first-child{ 
            opacity:.99; 
        } 
        span{ 
            position: absolute; 
            display: block; 
            height: 100px; 
            width: 100px; 
        } 
        .red{ 
            background-color: red; 
            z-index: 1 
        } 
        .green{ 
            top: 40px; 
            left: 40px; 
            background-color: green; 
        } 
        .blue{ 
            top: 80px; 
            left: 80px; 
            background-color: blue; 
        }

<div> 
    <span class="red"></span> 
</div> 
<div> 
    <span class="green"></span> 
</div> 
<div> 
    <span class="blue"></span> 
</div> 

 

image

 

解決方案

這個解決方法是在第一個<div>裏(紅色<span>的父節點)添加一個小於1的opacity屬性值。下面就是被添加的CSS的例子:開發

div:first-child{
opacity:.99;
}文檔

很神奇吧,但仍然百思不得其解,而且不相信opacity能決定哪一個元素堆在前面。如今就瞭解一下z-index。get

堆棧順序

z-index看上去如此簡單:高的z-index堆在低的z-index的前面,對嗎?這其實是錯的,是z-index問題的一部分。它看上去如此的簡單,以致於不少開發者沒有花相應的時間去讀相關的規則。

每個在HTML文檔中的元素既能夠在其餘元素的前面,也能夠在其餘元素的後面。這就是所謂的堆棧順序。決定這個順序的規則被十分清楚的定義在說明文檔中,可是就像以前我已經提到過,這些文檔沒有被大多數開發者們徹底弄明白。

當z-index和position屬性不被包括在內時,這些規則至關簡單:基本上,堆棧順序和元素在HTML中出現的順序同樣。(好吧,實際上是有一點複雜的,可是隻要你不使用壓縮邊界來重疊行內元素,你可能不會遇到邊界問題。)

當你把位置屬性也包括在內介紹時,任何定位元素(和他們的子元素)都在非定位元素前被顯示出來。(說一個元素被「定位」意思是它有一個不一樣於靜態的位置值,例如相對的,絕對的,等等。)

最後,當z-index被說起時,事情變的有點兒複雜。最初,很天然的假設帶有高z-index值的元素會在帶有低z-index值的元素前面,可是後來發現沒那麼簡單。首先,z-index只對定位元素起做用。若是你嘗試對非定位元素設定一個z-index值,那麼確定不起做用。其次,z-index值能建立堆棧上下文環境,而且忽然發現看似簡單的東西變的更加複雜了。

堆棧上下文

一組具備共同雙親的元素,按照堆棧順序一塊兒向前或向後移動構成了所謂的堆棧上下文。充分理解堆棧上下文是真正掌握z-index和堆棧順序工做原理的關鍵。

每個堆棧上下文都有一個HTML元素做爲它的根元素。當一個新的堆棧上下文在一個元素上造成,那麼這個堆棧上下文會限制全部的子元素以堆棧的順序存儲在一個特別的地方。那意味着一旦一個元素被包含在處於底部堆棧順序的堆棧上下文中,那麼就沒有辦法先出現於其餘處於更高的堆棧順序的不一樣堆棧上下文元素,就算z-index值是十億也不行

如今,堆棧上下文有三種方法能夠在一個元素上造成:

  1. 當一個元素是文檔的根元素時(<html>元素)。
  2. 當一個元素有一個position值而不是static,有一個z-index值而不是auto.
  3. 當一個元素有一個opacity值小於1

前兩種造成堆棧上下文的方法具備很大意義而且被廣大Web開發者所理解(即便他們不知道這些被叫作什麼)。第三種方法(opacity)幾乎歷來沒在w3c說明文檔以外被說起過。

用堆棧順序決定一個元素的位置

實際上,爲一個頁面上的全部元素決定全局堆棧順序(包括邊界、背景、文本節點、等等)是極度複雜的,而且遠遠超越了本文講述的範圍。可是咱們最大的目的,就是基本瞭解這個順序,它可以在很長一段時間內幫助咱們提升CSS開發的可預測性。因此,讓咱們打破順序,分解爲獨立的堆棧上下文。

在一樣堆棧上下文裏的堆棧順序

下面是幾條基本的規則,來決定在一個單獨的堆棧上下文裏的堆棧順序(從後向前):

  1. 堆棧上下文的根元素
  2. 定位元素(和他們的子元素)帶着負數的z-index值(高的值被堆疊在低值的前面;相同值的元素按照在HTML中出現的順序堆疊)。
  3. 非定位元素(按照在HTML中出現的順序排序)
  4. 定位元素(和他們的子元素)帶着auto的z-index值(按照在HTML中出現的順序排序)
  5. 定位元素(和他們的子元素)帶着正z-index值(高的值被堆疊在低值的前面;相同值的元素按照在HTML中出現的順序堆疊)

注 解:定位元素帶有負的z-index值被在一個堆棧上下文中先排序,這意味着他們出如今全部其餘元素的後面。正因如此,它使一個元素出如今本身父元素以後 成爲可能,這之前一般是不可能的事。固然,這侷限於它的父元素與它在同一個堆棧上下文,而且不是那個堆棧上下文的根元素。

全局堆棧順序

堅決的理解了爲何/何時新的堆棧上下文造成,同時掌握了同一個堆棧上下文的堆棧順序,如今讓你來找出一個特定元素將出如今全局堆棧裏的順序不是那麼糟糕了吧?

避免錯誤的關鍵是可以發現新的堆棧上下文何時造成。若是你對一個元素設置了z-index值爲十億可是它沒有在堆棧順序中向前移動,檢查一下它的祖先樹,看是否它的父節點造成了堆棧上下文。若是是那樣的話,你的z-index值即便有十億也不會給你帶來好處。

回到例子

回到以前的原始問題,我已經重建了這個HTML的結構,添加了一些註釋,每個標籤指明瞭它在堆棧裏的順序。這個順序是假設最初的CSS。

<div><!-- 1 -->
        <span class="red"><!-- 6 --></span>
    </div>
    <div><!-- 2 -->
        <span class="green"><!-- 4 --></span>
    </div>
    <div><!-- 3 -->
        <span class="blue"><!-- 5 --></span>
    </div>

當咱們添加opacity到第一個<div>,堆棧順序像下面這樣改變:

<div><!-- 1 -->
        <span class="red"><!-- 1.1 --></span>
    </div>
    <div><!-- 2 -->
        <span class="green"><!-- 4 --></span>
    </div>
    <div><!-- 3 -->
        <span class="blue"><!-- 5 --></span>
    </div>

span.red曾經的順序是6,但如今改成1.1。我已經使用「.」來標註一個新的上下文環境的造成。span.red如今是那個新的上下文的第一個元素。

如今彷佛更清晰了,關於爲何紅色盒子跑到其餘盒子的後面。原始的例子只包含兩個堆棧上下文,根元素和造成span.red的那個。當咱們添加 opacity到span.red的父節點上,造成了第三個堆棧上下文,結果顯示在span.red上的z-index值只能應用在那個新的堆棧上下文 中。由於第一個<div>(應用opacity的那個)和它的兄弟元素沒有position或者z-index值的集合,他們的堆棧順序是由 他們在HTML裏的源順序決定的,也就是說第一個<div>,和它的堆棧上下文裏的全部元素被第二個和第三個<div>元素分離。

總結

簡單來講,opacity會創造新的堆棧上下文,z-index比較通常是在同一堆棧內比較纔有效果 。mozzila官方https://developer.mozilla.org/en-US/docs/CSS/Understanding_z-index/The_stacking_context?redirectlocale=en-US&redirectslug=Understanding_CSS_z-index%2FThe_stacking_context

相關文章
相關標籤/搜索