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


以下內容根據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 specified

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

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

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

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

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

注意: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.

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

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


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

  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是創建父級層疊上下文的元素。
從渲染樹的頂層開始遍歷:
1、如果the element是根元素:

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

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)

3、擁有負的z-index值的定位的子節點形成的層疊上下文,負數最小的最先渲染,然后根據樹tree order渲染。

4、對於樹順序中的在文檔流(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)

5、對於樹順序中所有非定位的浮動子節點,渲染這些浮動子節點時,當做他們好像也形成了一個新的層疊上下文。但是,如果是定位的子節點和確實創建了一個新的層疊上下文的子節點,那么這兩種子節點還是處在父級的層疊上下文中,而不是他們創建的那個。

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

 

6、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).

 

7、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).


8、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.

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

10、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.)

 

參考資料:

1、z-index

2、Elaborate description of Stacking Contexts

3、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>

效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM