在正式开始介绍前,我们先提出这样一个疑问:
当两个元素位置互相堆叠在一起时,CSS 样式是如何决定哪个元素显示在前,哪个元素显示在后的呢?
为了解决这个问题,在左右、上下的布局基础上,CSS 2.1 引入了第三维度Z 轴的概念。CSS 将所有元素都被纳入一个Stacking Context中,根据某种规则控制元素堆叠的优先顺序,下面主要详细介绍一下这种规则。
Stacking Context 介绍
CSS 2.1 Spec 对Stacking Context的描述:
The order in which the rendering tree is painted onto the canvas is described in terms of stacking contexts.
我对这句话的理解是:Stacking Context有着一套规范元素堆叠顺序的规则。在渲染页面时,根据这套顺序规则依次在 Z 轴上显示不同元素。
Stacking Context 的特性
- 每个文档布局中存在多个
Stacking Context。而产生一个新的Stacking Context是有条件的「详见下文」 - 在每个
Stacking Context中可以嵌套其它的Stacking Context - 每个
Stacking Context中的元素位置和同级的Stacking Context中元素位置的顺序是互相独立的 - 每个
Stacking Context是自包含的,即当父元素形成一个Stacking Context「此时作为后代元素的Parent Stacking Context」,所有内部后代元素的堆叠顺序都仅限在Parent Stacking Context比较Stacking Context 内部元素排列顺序规则
按抵部->顶部顺序,可以抽象成七层布局:
归属于不同 Stacking Context 的元素顺序比较
上面介绍的堆叠顺序规则只用于比较同属于一个Parent Stacking Context的元素堆叠顺序。如果两个元素属于两个不同的Parent Stacking Context,那么它俩的顺序是由Parent Stacking Context的顺序决定的。
这句话说的有点绕,我们用图例来解释:
从图例中可以看到,DIV #2.1元素位置在DIV #1.1和DIV #1.2之下,尽管它的z-index值为 100。产生这个现象的原因就是因为DIV #2.1和DIV #1.1不在同一个Parent Stacking Context。所以此时需要找到DIV #2.1的Parent Stacking Context,即为DIV #2,此时比较DIV #2和DIV #1.1的堆叠顺序,因为DIV #2的z-index值为 1,所以它在DIV #1.1元素的下方,同时DIV #2.1的位置顺序受限于DIV #2,最后的排布顺序就如图所示。
图例解释说明:
- DIV #n,#n.n,#n.n.n 表示互为父-子元素关系,具体
HTML结构层次:
- Body
- DIV #1
- DIV #1.1
- DIV #1.2
- DIV #2
* DIV #2.1 * DIV #2.1.1 * DIV #2.1.2
- 绿色背景表示根元素「即
<html>」产生的Stacking Context- 颜色相同的元素表示它们同属于一个
Parent Stacking Context,Stacking Context层次关系:
- Root
- DIV #1
- DIV #1.1
- DIV #1.2
- DIV #2
- DIV #2.1
- DIV 2.1.1
- DIV 2.1.2
既然元素处于哪个Parent Stacking Context也会影响元素显示顺序,那么我们来看看元素的Parent Stacking Context是如何产生的:
最外层的
Stacking Context是根元素产生的,那么我们可以理解为它是所有元素的Parent Stacking Context。但当有新的Stacking Context产生时,这个新Stacking Context就是所有后代元素的Parent Stacking Context。以此类推,每当父元素产生一个新Stacking Context,就给后代元素提供了一个Parent Stacking Context。
产生新 Stacking Context 的条件
Root element「可以理解为第一个Stacking Context,用来包含其它的Stacking Context」Positioned元素的z-index值不是auto- 元素的
Opacity值小于 1「可以看作是给普通元素增加了Position属性,且z-index值为 0「详细可见 CSS Spec 2.1」 - Chrome 22+ 和 Mobile WebKit,
z-index值为auto的fixed position元素
Positioned 元素堆叠顺序规则
上面介绍了每一个Stacking Context内部元素的堆叠顺序,这里进一步详细介绍Positioned元素的堆叠顺序。
z-index 的作用
Positioned元素的堆叠顺序是由z-index决定的。z-index有2个作用:
- 决定
Positioned元素的Stack Level「可以理解为堆叠优先级,Stack Level值为整数,值大的放在上层」 - 决定是否形成一个新的
Stacking Context
z-index 属性值
z-index 有两个属性值:<integer>和<auto>「注:只有Positioned元素的Z-index值才有效」。
<integer>:当Z-index设置了一个整数「负整数,零,正整数」时,Positioned元素就产生了一个新的Stacking Context,同时这个整数代表了当前元素的Stack Level<auto>:该值说明当前元素的Stack Level值为 0。但此时并没有产生新的Stacking Context,除非这个元素是个根元素「注:这里可以看出z-index = auto和z-index = 0的区别」
总结
- 任意一个元素都归属一个
Stacking Context,Stacking Context可以互相嵌套,从而形成一个Stacking Context层级体系。「Root element是一个初始的Stacking Context,它包裹了其它的Stacking Context」 - 在每一个
Stacking Context内部,有特定堆叠优先级规则决定不同类型元素的堆叠顺序「Positioned元素的堆叠顺序由z-index值决定」 - 当两个元素归属于不同的
Parent Stacking Context时,它们的堆叠顺序互不干扰