標籤:

CSS中的Z-Index和堆疊上下文

之前對CSS中的Z-Index屬性一直存在著誤解。簡單的認為比較不同元素的Z-Index大小就可以決定不同元素在Z軸上的繪製順序了。其實最近遇到了一些問題,才發現CSS中的堆疊遠遠沒有那麼簡單。

先看看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只會對定位元素起作用,並且默認是不繼承的。對於定位元素來說,設置z-index可能會有如下的作用:

  • 決定元素在當前堆疊上下文(stacking context)中的堆疊層級

當z-index的值為integer的時候,integer的值就指定了元素在當前的堆疊上下文中的堆疊層級,並且會建立一個新的堆疊上下文

  • 決定元素是否建立一個新的堆疊上下文

除了html元素之外,z-index值為auto(default value)的元素不會生成新的堆疊上下文,並且在當前的堆疊上下文中的堆疊層級按照0來計算

這裡提到了一個概念堆疊上下文,spec中其實對堆疊上下文的概念提及不多,我找到了以下的描述:

The order in which the rendering tree is painted onto the canvas is described in terms of stacking contexts.

Stacking contexts can contain further stacking contexts.

A stacking context is atomic from the point of view of its parent stacking context;

boxes in other stacking contexts may not come between any of its boxes.

我們可以了解到:

  1. 由堆疊上下文決定繪製的順序
  2. 堆疊上下文可以包含更多的子堆疊上下文
  3. 第三句話比較晦澀,按照我的理解其含義是: 從父級堆疊上下文的角度來看,不會關心子堆疊上下文的子孫的堆疊順序。而上只會關心子級之間的堆疊順序。

在CSS3中,除了z-index: integer的定位元素和根元素之外兩種途徑,有更多的方式來生成堆疊上下文:

  • z-index不為auto的flex item. 即 父元素display為flex/inline-flex的元素
  • opacity小於1的元素
  • transform不為none的元素
  • filter不為none的元素
  • mix-blend-mode不為normal的元素
  • position為fixed的元素
  • etc...

按照標準的規定,在同一個堆疊上下文中,不同元素的繪製層次從遠到近按照下面的順序, 即使是沒有設置z-index的元素,繪製的時候也是會有層疊順序的:

  • 背景和邊框
  • 堆疊層級為負數的子堆疊上下文
  • 處於文檔流中的,非inline, 非positioned的後代元素
  • 非positioned的浮動元素
  • 處於文檔流中的,非positioned的inline元素, 包括inline-table, inline-block.
  • 堆疊層級為0的子堆疊上下文和堆疊層級為0的的定位後代元素。
  • 堆疊層級為正數的子堆疊上下文

除了上面的堆疊層次之外,還有一點需要注意,當同一堆疊上下文中的元素之間堆疊層級一致,並且發生層疊的時候,在DOM流中處於後面的元素會覆蓋前面的元素。

推薦閱讀:

Adobe Brackets 用來寫 HTML 和 CSS 有什麼優勢和技巧?
CSS 偽元素有哪些不得了的用法?
#00你認真學了css?
深入常用CSS聲明(一) —— Background

TAG:CSS |