CSS——關於z-index及層疊上下文(stacking context)

如下內容根據CSS規範翻譯。css

z-index

'z-index'
Value: auto | <integer> | inherit
Initial: auto
Applies to: positioned elements
Inherited: no
Percentages: N/A
Media: visual
Computed value: as specifiedhtml

注意:z-index屬性只能應用於position屬性不爲static的元素,即定位元素。css3

對於定位元素來講,z-index屬性指定:web

  1. 在當前層疊上下文中該定位元素盒子的堆疊層級(stack level);
  2. 該定位元素盒子是否造成新的層疊上下文(stacking context)。

z-index屬性可取值的含義:
<integer>
若是值爲整數,那麼這個整數指的是這個盒子(the generated box)在當前層疊上下文中的堆疊層級。同時,這個盒子對內也造成一個層疊上下文。express

auto
若是值爲auto,那麼這個盒子(the generated box)在當前層疊上下文中的堆疊層級爲0。同時,這個盒子對內不造成層疊上下文,除非他是根元素。canvas

注意:z-index值爲 0 與z-index值爲auto的區別。區別是前者對內建立一個新的層疊上下文,後者不建立新的層疊上下文。除了這點區別,二者的層級是同樣的。
In this section, the expression "in front of" means closer to the user as the user faces the screen.app

在CSS 2.1中,每個盒子處在三維空間中。除了水平軸和垂直軸外,還有一個z軸(z-axis),這三個軸共同決定了盒子在三維空間中的位置。
盒子在z軸上的位置與盒子之間的重疊關係尤爲相關。
下面討論盒子如何在z軸上定位。ide

每個盒子都處在層疊上下文中。若是在給定的層疊上下文中的給每個定位的盒子(positioned box)指定一個整數的堆疊層級,那麼這個堆疊層級就是該定位盒子相對於同一層疊上下文中其餘定位盒子在z軸上的位置。擁有較大堆疊層級的盒子處在擁有較小堆疊層級的盒子的前面,即距離用戶更近。堆疊層級能夠爲負值。在同一層疊上下文中,擁有相同堆疊層級的盒子根據後來居上的規則堆疊。flex


產生層疊上下文的狀況(不全面):ui

  1. 根元素造成根層疊上下文(the root stacking context)。
  2. 任何定位元素(position不爲static的元素)且該元素的z-index屬性不爲auto。

隨着CSS的不斷髮展,也會有新的CSS屬性會引入層疊上下文,好比CSS 3中的opacity屬性等。
層疊上下文與包含塊不存在絕對的相關關係。

在每個層疊上下文中,如下層次按照後來居上的規則繪製(序號越大,堆放得越靠前,距離用戶越近):
Within each stacking context, the following layers are painted in back-to-front order:

  1. 元素的background和borders
  2. 擁有負堆疊層級(negative stack levels)的子層疊上下文(child stacking contexts)
  3. 在文檔流中的(in-flow),非行內級的(non-inline-level),非定位(non-positioned)的後代元素
  4. 非定位的浮動元素
  5. 在文檔流中的(in-flow),行內級的(inline-level),非定位(non-positioned)的後代元素,包括行內塊級元素(inline blocks)和行內表格元素(inline tables)
  6. 堆疊層級爲 0 的子堆疊上下文(child stacking contexts)和堆疊層級爲 0 的定位的後代元素
  7. 堆疊層級爲正的子堆疊上下文

Within each stacking context, positioned elements with stack level 0 (in layer 6), non-positioned floats (layer 4), inline blocks (layer 5), and inline tables (layer 5), are painted as if those elements themselves generated new stacking contexts, except that their positioned descendants and any would-be child stacking contexts take part in the current stacking context.

上述關於層次的繪製規則遞歸地適用於任何層疊上下文。

層疊上下文

MDN中列舉的建立新的層疊上下文的情形

文檔中的層疊上下文由知足如下任意一個條件的元素造成:

  1. 根元素 (HTML),
  2. z-index 值不爲 "auto"的 絕對/相對定位,
  3. 一個 z-index 值不爲 "auto"的 flex 項目 (flex item),即:父元素 display: flex|inline-flex,
  4. opacity 屬性值小於 1 的元素(參考 the specification for opacity),
  5. transform 屬性值不爲 "none"的元素,
  6. mix-blend-mode 屬性值不爲 "normal"的元素,
  7. filter值不爲「none」的元素,
  8. perspective值不爲「none」的元素,
  9. isolation 屬性被設置爲 "isolate"的元素,
  10. position: fixed
  11. 在 will-change 中指定了任意 CSS 屬性,即使你沒有直接指定這些屬性的值(參考 這篇文章)
  12. -webkit-overflow-scrolling 屬性被設置 "touch"的元素

在層疊上下文中,其子元素一樣也按照上面解釋的規則進行層疊。 特別值得一提的是,其子元素的 z-index 值只在父級層疊上下文中有意義。子級層疊上下文被自動視爲父級層疊上下文的一個獨立單元。

總結:

給一個 HTML 元素定位和 z-index 賦值建立一個層疊上下文,(opacity 值不爲 1 的也是相同)。
層疊上下文能夠包含在其餘層疊上下文中,而且一塊兒建立一個有層級的層疊上下文。
每一個層疊上下文徹底獨立於它的兄弟元素:當處理層疊時只考慮子元素。
每一個層疊上下文是自包含的:當元素的內容發生層疊後,整個該元素將會 在父層疊上下文中 按順序進行層疊。
Note: 層疊上下文的層級是 HTML 元素層級的一個層級,由於只有某些元素纔會建立層疊上下文。能夠這樣說,沒有建立本身的層疊上下文的元素 將被父層疊上下文包含。

層疊上下文的層疊規則

先明確兩個定義
樹順序 Tree Order

計算完元素自身的周邊屬性(背景顏色、背景圖片、邊框等)後,對渲染樹進行前序深度優先遍歷。
Preorder depth-first traversal of the rendering tree, in logical (not visual) order for bidirectional(雙向) content, after taking into account properties that move boxes around.

元素 Element
在如下描述中,「元素」指的是實實在在的元素、僞元素以及匿名盒。僞元素和匿名盒被做爲子節點(descendants)處理。
In this description, "element" refers to actual elements, pseudo-elements, and anonymous boxes. Pseudo-elements and anonymous boxes are treated as descendants in the appropriate places. For example, an outside list marker comes before an adjoining ':before' box in the line box, which comes before the content of the box, and so forth.

渲染順序
堆疊層次的最底層距離用戶最遠,最上層距離用戶最近,如圖:

層疊上下文(也能夠叫堆棧上下文)的背景和最小負數定位(z-index爲負)的子層疊上下文在層疊順序(stack)的底層,最大的正數定位的子層疊上下文在層疊順序(stack)的頂層。


默認狀況下,若是一個畫布(canvas)被包含在另外一個畫布中,那麼它將是透明的;若是它沒有被包含在另外一個畫布中,它將被用戶代理指定一個默認顏色。根元素包含在畫布中,這個畫布能夠向外無限擴展。最初,視口(viewport)的左上角被綁定在畫布的原點。

造成層疊上下文的元素的子節點(descendants)的渲染順序(參考z-index屬性):
(按照if語句嵌套的方式理解下列規則)
注意:the element是建立父級層疊上下文的元素。
從渲染樹的頂層開始遍歷:
一、若是the element是根元素:

  1. 元素的背景顏色覆蓋整個畫布
  2. 元素的背景圖片覆蓋整個畫布,起點在畫布的原點。

二、若是the element是塊級元素、列表項(list-item)或其餘的與塊級元素同級的元素(根元素除外):

  1. 背景顏色
  2. 背景圖片
  3. 邊框

     不然,若是the element是塊級的表格元素:

  1. 表格得背景顏色,而後背景圖片
  2. 列組(column group)的背景顏色,而後背景圖片
  3. 列(column)的背景顏色,而後背景圖片
  4. 行組(row group)的背景顏色,而後背景圖片
  5. 行(row)的背景顏色,而後背景圖片
  6. 表單元格(cell)的背景顏色,而後背景圖片
  7. 全部的表格邊框(in tree order for separated borders)

三、擁有負的z-index值的定位的子節點造成的層疊上下文,負數最小的最早渲染,而後根據樹tree order渲染。

四、對於樹順序中的在文檔流(in-flow),非定位,塊級(block-level)子節點,若是該子節點是塊級元素、列表項(list-item)或其餘的與塊級元素同級的元素:

  1. 背景顏色
  2. 背景圖片
  3. 邊框

     不然,若是該子節點是表格元素:

  1. 表格得背景顏色,而後背景圖片
  2. 列組(column group)的背景顏色,而後背景圖片
  3. 列(column)的背景顏色,而後背景圖片
  4. 行組(row group)的背景顏色,而後背景圖片
  5. 行(row)的背景顏色,而後背景圖片
  6. 表單元格(cell)的背景顏色,而後背景圖片
  7. 全部的表格邊框(in tree order for separated borders)

五、對於樹順序中全部非定位的浮動子節點,渲染這些浮動子節點時,當作他們好像也造成了一個新的層疊上下文。可是,若是是定位的子節點和確實建立了一個新的層疊上下文的子節點,那麼這兩種子節點仍是處在父級的層疊上下文中,而不是他們建立的那個。

第6條和第7條實在翻譯不下去了,仍是看原文吧。

 

六、If the element is an inline element that generates a stacking context, then:

    1. For each line box that the element is in:

      1. Jump to 7.2.1 for the box(es) of the element in that line box (in tree order).

 

七、Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:

    1. If the element is a block-level replaced element, then: the replaced content, atomically.

    2. Otherwise, for each line box of that element:

      1. For each box that is a child of that element, in that line box, in tree order:

        1. background color of element.

        2. background image of element.

        3. border of element.

        4. For inline elements:

          1. For all the element's in-flow, non-positioned, inline-level children that are in this line box, and all runs of text inside the element that is on this line box, in tree order:

            1. If this is a run of text, then:

              1. any underlining affecting the text of the element, in tree order of the elements applying the underlining (such that the deepest element's underlining, if any, is painted topmost and the root element's underlining, if any, is drawn bottommost).
              2. any overlining affecting the text of the element, in tree order of the elements applying the overlining (such that the deepest element's overlining, if any, is painted topmost and the root element's overlining, if any, is drawn bottommost).
              3. the text.
              4. any line-through affecting the text of the element, in tree order of the elements applying the line-through (such that the deepest element's line-through, if any, is painted topmost and the root element's line-through, if any, is drawn bottommost).
            2. Otherwise, jump to 7.2.1 for that element.

          For inline-block and inline-table elements:

          1. For each one of these, treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.

          For inline-level replaced elements:

          1. the replaced content, atomically.

        Some of the boxes may have been generated by line splitting or the Unicode bidirectional algorithm.

      2. Optionally, the outline of the element (see 10 below).

    3. Optionally, if the element is block-level, the outline of the element (see 10 below).


八、All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0', treat the stacking context generated atomically.

九、Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.

十、Finally, implementations that do not draw outlines in steps above must draw outlines from this stacking context at this stage. (It is recommended to draw outlines in this step and not in the steps above.)

 

參考資料:

一、z-index

二、Elaborate description of Stacking Contexts

三、The stacking context

下面看例子(沒有考慮opacity),例子以根元素建立的層疊上下文爲基礎。

例子一

CSS代碼:

div {
        font: 12px Arial;
    }
    body{
        border:1px solid white;
    }
    span.bold { font-weight: bold; }
    .text-style{
        text-align: center;
        border:1px solid black;
    }
    #div1{
        float: left;
        width: 300px;
        height: 50px;
        background-color: pink;
        text-align: right;
    }
    #div2{
        position: absolute;
        width: 280px;
        height:120px;
        top: 50px;
        background-color: gray;
        text-align: right;
    }
    
    #div3{
        width: 450px;
        height: 300px;
        text-align: right;
        margin-top: 20px;
    }
    #div4{
        position: relative;
        width: 160px;
        height: 80px;
        z-index: 1;
        top:-300px;
        background-color: rgb(34,200,150);
    }

 

HTML代碼:

 1 <div id="div1" class="text-style">
 2         <p><span class="bold">DIV #1</span>
 3         <br />float left</p>
 4     </div>
 5 
 6     <div id="div2" class="text-style">
 7         <p><span class="bold">DIV #2</span>
 8         <br />position: absolute</p>
 9     </div>
10 
11     <div id="div3" class="text-style">
12         <p><span class="bold">DIV #3</span>
13         <br />no positioning, no float
14         </p>
15     </div>
16 
17 
18     <div id="div4" class="text-style">
19         <p><span class="bold">DIV #4</span>
20         
21         <br />position: relative
22          <br /> z-index: 1
23          </p>
24     </div>

效果:

從圖中能夠看出,浮動元素,定位元素,常規元素,設置了z-index的元素,四種元素在同一個層疊上下文中的層疊次序一目瞭然。

例子二

 CSS代碼:

 1 #div5{
 2         position: absolute;
 3         border: 1px solid black;
 4         width:350px;
 5         height: 300px;
 6         z-index: 0;
 7         background-color: #5555FF;
 8         text-align: right;
 9     }
10     #div6{
11         position: absolute;
12         border: 1px solid black;
13         width:250px;
14         height: 200px;
15         z-index: auto;
16         background-color: #FFBB66;
17         text-align: right;
18     }
19     #div7{
20         position: absolute;
21         border: 1px solid black;
22         width:450px;
23         height: 180px;
24         z-index: -1;
25         background-color: #66FF66;
26         text-align: right;
27     }
28     #div8{
29         position: relative;
30         border: 1px solid black;
31         width:150px;
32         height: 250px;
33         z-index: 1;
34         background-color: #E38EFF;
35     }

HTML代碼:

 1 <div id="div5" class="text-style">
 2         <p><span class="bold">DIV #5</span>
 3         <br />position: absolute
 4         <br /> z-index: 0
 5         </p>
 6     </div>
 7 
 8     <div id="div6" class="text-style">
 9         <p><span class="bold">DIV #6</span>
10         <br />position: absolute
11         <br /> z-index: auto
12         </p>
13     </div>
14 
15     <div id="div7" class="text-style">
16         <p><span class="bold">DIV #7</span>
17         <br />position: absolute
18         <br /> z-index: -1
19         </p>
20     </div>
21 
22     <div id="div8" class="text-style">
23         <p><span class="bold">DIV #8</span>
24         <br />position: relative
25          <br /> z-index: 1
26          </p>
27     </div>

效果:

相關文章
相關標籤/搜索