CSS-层叠上下文
Posted natsu-cc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSS-层叠上下文相关的知识,希望对你有一定的参考价值。
前言:
当多个 html 元素在浏览器视窗中发生重叠时,浏览器会怎么安排哪个元素显示在上、哪个显示在下呢?其实所有元素在发生层叠时的表现都是按照一定的优先级顺序的,这些顺序规则都是建立在 层叠上下文(The Stacking Context) 这个三维概念中。
-
层叠上下文:
假定用户正面向(浏览器)视窗或网页,而 HTML 元素沿着其相对于用户的一条虚构的 z 轴排开,层叠上下文就是对这些 HTML 元素的一个三维构想。众 HTML 元素基于其元素属性按照优先级顺序占据这个空间。(MDN) -
层叠水平:
“层叠水平”英文称作”stacking level”,决定了同一个层叠上下文中元素在z轴上的显示顺序。普通元素的层叠水平优先由层叠上下文决定,因此,层叠水平的比较只有在当前层叠上下文元素中才有意义。 -
层叠顺序:
“层叠顺序”英文称作”stacking order”. 表示元素发生层叠时候有着特定的垂直显示顺序,注意,这里跟上面两个不一样,上面的层叠上下文和层叠水平是概念,而这里的层叠顺序是规则。
层叠上下文特性:
注意:例子代码截取重要部分!
在同一个层叠上下文中,子元素按照层叠顺序规则进行层叠:
当不同层叠顺序的元素相比较时,不关心元素在 DOM 树中的结构关系:
<style>
.child {
position: relative;
z-index: -1;
}
</style>
<div class="parent">
<div class="child"></div>
</div>
<div class="parent" style="opacity: 0.6;">
<div class="child"></div>
</div>
左边实例中 Parent 元素不是层叠上下文元素,所以和 Child 元素是处于同一个层叠上下文中,而根据层叠顺序,普通流块级元素是叠在负 z-index 定位元素之上的。右边实例中 Parent 元素指定属性 opacity: 0.6,创建了一个层叠上下文,从而使 Child 元素包含在内,根据层叠顺序负 z-index 定位元素 会叠在根元素背景和边框之上。这样的表现说明,Parent 和 Child 元素的父子节点关系不会影响层叠关系。
在同一个层叠上下文中,当元素的层叠顺序相同时,按照元素在 HTML 中出现的顺序进行层叠:
<style>
.box-1 {
position: relative;
}
.box-2 {
position: absolute;
top: 50px;
left: 50px;
}
</style>
<div class="wrapper">
<div class="box-1"></div>
<div class="box-2"></div>
</div>
<div class="wrapper">
<div class="box-2"></div>
<div class="box-1"></div>
</div>
所有 z-index 属性值为 0 / auto 的定位元素的层叠顺序都是相同的,如实例中的 box-1 和 box-2 元素,可以看出它们发生层叠时遵循的是 在 HTML 中出现的先后顺序。
层叠上下文可以嵌套,内部层叠上下文及其所有子元素均受制于外部的层叠上下文。
每个层叠上下文和兄弟元素独立,也就是当进行层叠变化或渲染的时候,只需要考虑后代元素。
每个层叠上下文是自成体系的,当元素发生层叠的时候,整个元素被认为是在父层叠上下文的层叠顺序中:
<style>
.parent-1,
.parent-2,
.child-1,
.child-2 {
position: relative;
}
.parent-1 { z-index: 2; }
.parent-2 { z-index: 1; }
.child-1 { z-index: -1; }
.child-2 { z-index: 10; }
</style>
<div class="parent-1">
<div class="child-1"></div>
</div>
<div class="parent-2">
<div class="child-2"></div>
</div>
Child-1 和 Child-2 元素分别处于各自的父级层叠上下文元素 Parent-1 和 Parent-2 中。由于 Parent-1 是层叠于 Parent-2 之上的,即使 Child-1 的 z-index: -1 属性值小于 Child-2 的 z-index: 10,Child-2 也不能逾越其父级上下文覆盖在 Child-1 上面的。换句话说,子级层叠上下文的层级讨论只在其父级层叠上下文中有意义。
创建层叠上下文:
根据 MDN 里的解释,只要符合以下特征就形成了层叠上下文:
- html 根元素自身就会创建一个层叠上下文
- position 值为 absolute 或 relative 且 z-index 值不为 auto 的元素
- position 值为 fixed 或 sticky 的元素(注意:sticky 在老旧浏览器上不支持)
- flex 容器的子元素,且 z-index 值不为 auto
- grid 容器的子元素,且 z-index 值不为 auto
- opacity 属性值不为 1 的元素
- mix-blend-mode 属性不为 normal 的元素
- transform 属性值不为 none 的元素
- filter 属性值不为 none 的元素
- perspective 属性值不为 none 的元素
- clip-path 属性值不为 none 的元素
- mask / mask-image / mask-border 属性值不为 none 的元素
- isolation 属性值为 isolate 的元素
- -webkit-overflow-scrolling 属性值为 touch 的元素
- will-change 值设定了任一属性而该属性在非初始值(non-initial)时会创建层叠上下文
- contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素
在同一层叠上下文中元素会按照一定的规则进行层叠,比如设置 absolute 的元素会按照 z-index 的大小从上到下依次层叠。当然要比较 z-index 的大小只有在同一个层叠上下文中才有意义。
层叠顺序:
层叠顺序就是元素在层叠上下文中的显示规则。在此之前需要提前认识一个重要概念:z-index 只会对定位元素(非普通流)有效 !
这里需要分两种情况讨论:
- 如果层叠上下文元素不依赖z-index数值,则其层叠顺序是z-index:auto可看成z:index:0级别。
- 如果层叠上下文元素依赖z-index数值,则其层叠顺序由z-index值决定。
当元素发生层叠时,会按照下面的 7 阶层叠顺序来决定元素显示的前后顺序:
- 根元素的背景与边框;
- z-index < 0 的定位元素;
- 普通流中的块元素(display: block);
- 浮动块元素;
- 普通流中的行内元素(display: inline / display: inline-block);
- z-index 属性值为 0 / auto 的定位元素、其他子级层叠上下文元素;
- z-index > 0 的定位元素;
在同一个层叠上下文中,定位元素会按照 z-index 的大小从上到下进行层叠,如果 z-index 一样,那么后面的元素等级要大于前面的,「后来者居上」。
定位元素会层叠在普通元素的上面:
-
其根本原因就在于,元素一旦成为定位元素,其z-index就会自动生效,此时其z-index就是默认的auto,也就是0级别,根据上面的层叠顺序表,就会覆盖inline或block或float元素。
-
而不支持z-index的层叠上下文元素天然z-index:auto级别,也就意味着,层叠上下文元素和定位元素是一个层叠顺序的,于是当他们发生层叠的时候,遵循的是“后来居上”准则。
总结:
- 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。
- 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
- 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。
注意:
- 层叠上下文的层级是 HTML 元素层级的一个子级,因为只有某些元素才会创建层叠上下文。可以这样说,没有创建自己的层叠上下文的元素会被父层叠上下文同化。
- z-index 属性值为 0 / auto 的定位元素和不依赖 z-index 的子级层叠上下文元素顺序相同,会遵循在HTML中出现的先后顺序来层叠。
- 固定定位(position: fixed)的特殊性,绝对/相对定位元素是无法创建一个层叠上下文的,需要同时满足 z-index 值不为 auto 的条件。然而,固定定位元素就不需要满足这个条件,同样地,设置 z-index: auto 并不能撤销固定定位元素所创建的层叠上下文。
参考:
以上是关于CSS-层叠上下文的主要内容,如果未能解决你的问题,请参考以下文章