CSS基础:层叠顺序和层叠上下文
简介
在考虑到两个元素可能重叠的情况下,层叠顺序决定了那个元素在前面,那个元素在后面,这是针对普通元素而言。而层叠上下文和块级格式化上下文 (BFC) 一样,基本上也是由一些 CSS 属性创建的,它单独作为一个体系,也就是说内容的层叠顺序是以容器的层叠顺序为基准的,而与容器外部元素的层叠顺序无关,层叠上下文的创建可以分为以下三类:
(1) 页面根元素天生具有层叠上下文,称为根层叠上下文
(2) "z-index" 为数值的定位元素拥有自己的层叠上下文,数值越大,层叠顺序越高
(3) 某些 CSS3 属性也拥有自己的层叠上下文
元素的层叠顺序
如图所示:
(1) 层叠顺序大的元素会覆盖较小的元素
(2) 层叠顺序相同时,处于 DOM 流中后面的元素会覆盖前面的元素
(3) "background/border" 特指层叠上下文元素的背景和边框,如果一个元素是普通元素,没有创建单独的层叠上下文,并且它的子代有负的 "z-index",那这个子代就会隐藏在背景后面,因为它的子代是相对于根层叠上下文决定的。
示例1:
<!-- html -->
<div class="box"> <div class="order1"></div> </div>
//css .box { width: 200px;height: 200px; background: lightblue; } .order1 { width: 150px;height: 150px; background: red; position: relative; z-index: -1; }
运行结果:
示例2:
//css .box { width: 200px;height: 200px; background: lightblue; position: relative; z-index: 1; } .order1 { width: 150px;height: 150px; background: red; position: relative; z-index: -1; }
运行结果:
(4) "z-index:auto" 和 "z-index:0" 虽然层叠顺序一样,也就是遵循规则 (2) 中 "后来者居上" 的原则,但是它们的区别在于后者会创建单独的层叠上下文。
示例1:
<!-- html --> <div class="box"> <div class="order1"><div class="child1"></div></div> <div class="order2"><div class="child2"></div></div> </div>
//css .box { height: 300px; position: relative; z-index: 1; } .order1 { width: 250px;height: 250px; background: red; position: absolute; z-index: auto; } .order1 .child1 { width: 50px;height: 50px; background: yellow; position: relative; z-index: 2; } .order2 { width: 200px;height: 200px; background: green; position: absolute; z-index: auto; } .order2 .child2 { width: 100px;height: 100px; background: blue; position: relative; z-index: 1; }
运行结果:
由于 "order1" 和 "order2" 的 "z-index:auto",虽然后者覆盖了前者,但是没有创建新的层叠上下文,因此它们的子代的层叠顺序其实是相对于同一个 "根层叠上下文",所以 "z-index" 值大的元素位于前面。
示例2:
将 "order1" 和 "order2" 设置为 "z-index:0"
运行结果:
同理,后者覆盖了前者,同时 "z-index:0" 创建了新的层叠上下文,子代层叠顺序是相对于父容器决定的,而 "order1" 已经被 "order2" 覆盖,其子代无论将 "z-index" 设置为多大都无法影响父容器外部的层叠顺序。
(5) 定位元素的 "z-index" 属性默认生效,并且值为 "auto",这也是为什么定位元素的层叠顺序要高于块级、浮动和内联元素的原因
(6) CSS3 中某些新属性会创建新的层叠上下文,层叠顺序与 "z-index:auto" 相同,例如:"flex" 布局的元素,"opacity" 不为1的元素,"transform" 不是1的元素...