Appearance
层叠上下文、层叠水平和 z-index
层叠水平
层叠水平也叫层叠等级、层叠等级 ,每一个元素都有一个层叠水平,决定了同一个层叠上下文中元素在 z 轴的显示顺序。其遵循'后来居上'和'谁大谁上'的原则。
在同一个层叠上下文中,就像前面所说的 BFC(块级格式化上下文)中也会存在很多子子孙孙元素,那么这些元素的内容文字、背景是如何相互影响的?
1. 块级元素
我们比较两个同级别的元素 兄弟元素
1.1. 块级元素与块级元素比较
html
<h2>块级元素与块级元素比</h2>
<div class="container">
<div class="bg-org row1" style="width: 100px;height: 100px;">11111111111111111</div>
<div class="bg-blue row2" style="width:100px;height:100px;margin-top: -100px;color: #fff;">
2222222222222222222222
</div>
</div>
效果如下:
默认后面的元素层级越高,但是背景的层级小于文字的层级 即 row1(背景) < row2(背景) < row1(文字) < row2(文字)
1.2. 行内元素与行内元素比较
html
<h2>行内元素与行内元素比</h2>
<div class="container">
<div class="bg-org row1" style="display:inline;width: 100px;height: 100px;">1111111111</div>
<div class="bg-blue row2" style="display:inline;width:100px;height:100px;margin-left: -107px;color: #fff;">
222222222
</div>
</div>
<div class="container">
<div class="bg-org row1" style="display:inline-block;width: 100px;height: 100px;">1111111111</div>
<div class="bg-blue row2" style="display:inline-block;width:100px;height:100px;margin-left: -107px;color: #fff;">
222222222
</div>
</div>
效果如下:
我们发现第二个元素完全覆盖了第一个元素整体,即后面的元素层级高,但是前面的文字也小于后面的背景 即 row1(背景) < row1(文字) < row2(背景) < row2(文字)
1.3. 行内元素与块级元素比较
html
<h2>行内元素与行内元素比</h2>
<div class="container">
<div class="bg-org row1" style="display:inline;width: 100px;height: 100px;">1111111111</div>
<div class="bg-blue row2" style="display:inline-block;;width:100px;height:100px;margin-left: -107px;color: #fff;">
222222222
</div>
</div>
<div class="container">
<div class="bg-blue row2" style="display:inline-block;;width:100px;height:100px;margin-left: -107px;color: #fff;">
222222222
</div>
<div class="bg-org row1" style="display:inline;width: 100px;height: 100px;">1111111111</div>
</div>
效果如下:
不管谁前谁后,行内元素都整体覆盖块级元素
2. 浮动元素
2.1. 浮动元素与浮动元素比较
html
<h2>浮动元素与浮动元素比</h2>
<div class="container">
<div class="bg-org float1" style="float:left;width: 100px;height: 100px;">浮动1</div>
<div class="bg-blue float2" style="float:left;width:100px;height:100px;margin-left: -107px;">浮动2</div>
<div style="clear: both;"></div>
</div>
效果如下:
浮动与浮动相比,后来者居上。即 float1(背景) < float1(文字) < float2(背景) < float2(文字)
2.2 浮动元素与块级元素比较
html
<h2>浮动元素与块级元素</h2>
<div class="container">
<div class="bg-org float1" style="float:left;width: 100px;height: 100px;color: #fff;">浮动1</div>
<div class="bg-blue block1" style="width:100px;height:100px;margin-left: -107px;">块级元素</div>
</div>
效果如下:
不管谁前谁后,浮动都整体覆盖块级元素。即 block1(背景) < block1(文字) < float1(背景) < float1(文字)
2.3 浮动元素与行内元素(行内块)比较
html
<h2>浮动元素与行内元素(行内块)比较</h2>
<div class="container">
<div class="bg-org inline1" style="display:inline;width: 90px;height: 100px;">行内元素(行内块)</div>
<div class="bg-blue float1" style="float:left;width:100px;height:80px;color: #fff;">浮动1</div>
</div>
效果如下:
不管谁前谁后, 浮动元素不会与行内元素占用一块地方,所以没有谁覆盖谁的概念
3. 定位元素
3.1. 定位元素与定位元素相比
html
<h2>定位元素与定位元素</h2>
<div class="container">
<div class="bg-org position1" style="position:relative;width: 100px;height: 100px;">定位1</div>
<div class="bg-blue position2" style="position:relative;width:100px;height:100px;margin-top: -107px;color: #fff;">
定位2
</div>
</div>
效果如下:
浮动与浮动相比,后来者居上。即 position1(背景) < position1(文字) < position2(背景) < position2(文字)
3.2. 定位元素与块级元素相比
html
<h2>定位元素与块级元素相比</h2>
<div class="container">
<div class="bg-org position1" style="position:relative; width: 100px;height: 100px;">定位1</div>
<div class="bg-blue block1" style="width:100px;height:100px;margin-top: -107px;">块级元素</div>
</div>
效果如下:
不管谁前谁后,定位元素都整体覆盖块级元素。即 block1(背景) < block1(文字) < position1(背景) < position1(文字)
3.3. 定位元素与浮动元素相比
html
<h2>定位元素与浮动元素相比</h2>
<div class="container">
<div class="bg-org float1" style="float:left;width: 100px;height: 100px;color: #fff;">浮动元素</div>
<div class="bg-blue position1" style="position:relative; width:88px;height:100px;left: 10px">定位1</div>
</div>
效果如下:
不管谁前谁后,定位元素都整体覆盖浮动元素。即 float1(背景) < float1(文字) < position1(背景) < position1(文字)
但是 定位元素的文字内容被浮动元素挤出来了
我们将定位元素的宽度变大
这就是说明虽然定位元素整体覆盖了浮动元素,但是浮动元素的特性(占据空间)还是存在的。
3.4. 定位元素与行内(行内块)元素相比
html
<h2>定位元素与行内(行内块)元素相比</h2>
<div class="container">
<div class="bg-org inlineblock1" style="display:inline-block;width: 100px;height: 100px;">行内元素(行内块)</div>
<div
class="bg-blue position1"
style="position:relative;width:100px;height:100px;margin-top: -107px;margin-left: 10px;color: #fff;"
>
定位1
</div>
</div>
效果如下:
不管谁前谁后,定位元素都整体覆盖行内(行内块)元素。即 inlineblock1(背景) < inlineblock1(文字) < position1(背景) < position1(文字)
总结
兄弟元素间的覆盖 遵循后来者居上
定位元素 > 行内(行内块)元素 > 浮动元素 > 块级元素 > 背景
除块级元素之间比较存在 背景层次小于 内容的 其他都是整体覆盖。
当前前面的都没有牵扯到 z-index 的概念 当我们把一个定位元素 与一个设置 z-index 为 1 | 0 | auto 的块级元素比较的时候 块级元素整体覆盖了 定位元素
所以我们上面的排名修改一下
背景 < 块级元素 < 浮动元素 < 定位元素 < z-index = 0 | auto; < z-index 为正(当然 z-index 的值越大 层级越高)
当我们把 定位元素设 z-index 为负数与块级元素比较的时候,发现 块级元素覆盖了设置 z-index 为负数的定位元素 所以我们上面的排名修改一下
背景 < z-index 为负数 < 块级元素 < 浮动元素 < 定位元素 < z-index = 0 | auto; < z-index 为正(当然 z-index 的值越大 层级越高) 这就是著名的 7 阶层叠水平
加z-index总结
后来者居上
背景 < z-index 为负数 < 块级元素 < 浮动元素 < 定位元素 < z-index = 0 | auto; < z-index 为正(当然 z-index 的值越大 层级越高)
子从父原则 父小 子再大也没毛用。
当然前面层叠等级是在同一个层叠上下文下,且子孙元素没有形成新的层叠上下文,如果这时候我们添加上层叠上下文的概念。
层叠上下文
这时候我们就涉及到几个概念:1. 什么是层叠上下文? 2. 怎么形成层叠上下文 3. 层叠上下文间的比较(父子、兄弟、祖孙)
什么是层叠上下文
解释: HTML 中存在一个 z 轴的概念,就是我们面向电脑的这一方向就是 z 轴。而拥有层叠上下文的元素将离用户最近,默认时候只有根元素有层叠上下文,并且元素一旦使用了一些属性也将会产生一个层叠上下文,如我们常用的定位属性。
怎么形成层叠上下文
其实,层叠上下文也基本上是有一些特定的CSS属性创建的,一般有3种方法:
根元素<html>本身就具有层叠上下文。
普通元素设置position属性为非static值并设置z-index属性为具体数值,产生层叠上下文。(如果只是属性设置成position:relative;没有设置z-index或者z-index:auto;都不会形成层叠上下文)
IE6/IE7浏览器有个bug,就是z-index:auto的定位元素也会创建层叠上下文。
position:fixed, 在过去,position:fixed和relative/absolute在层叠上下文这一块是一路货色,都是需要z-index为数值才行。但是,不知道什么时候起,Chrome等webkit内核浏览器,position:fixed元素天然层叠上下文元素,无需z-index为数值。根据我的测试,目前,IE以及FireFox仍是老套路。
CSS3中的新属性也可以产生层叠上下文。
- z-index值不为auto的flex项(父元素display:flex|inline-flex).
- 元素的opacity值不是1.
- 元素的transform值不是none.
- 元素mix-blend-mode值不是normal.
- 元素的filter值不是none.
- 元素的isolation值是isolate.
- will-change指定的属性值为上面任意一个。
- 元素的-webkit-overflow-scrolling设为touch.
层叠上下文间的比较(父子、兄弟)
我们知道在层叠等级讲解中,同一个层叠上下文中元素间遵循下面的规则:
后来者居上
7阶层叠水平
在上下层次间比较
子级覆盖父级
除非上下级都是块级元素,那么就是 父级背景<子级背景<父级元素<子级元素。见上面的 3.1
那么这时候我们添加上层叠上下文的概念再进行一次比较
1. 兄弟层叠上下文的比较
html
<h2>兄弟都是层叠上下文的</h2>
<div class="container" style="position:relative;background-color: #ddd;height: 50px;z-index:0;">
<!-- 后面的覆盖前面的,显示层叠上下文1 -->
<div class="bg-blue stacking1" style="position:absolute;top: 0px;z-index:1;">层叠上下文1----</div>
<div class="bg-org stacking2" style="position:absolute;top: 0px;z-index:1;">层叠上下文2</div>
<img src="../css/timg.jpg" height="50" width="50" style="position:absolute;top: 0px;z-index:auto;">
</div>
效果图如下:
我们发现对于stacking1 和 stacking2 来说其z-index都为1,所以相同,且他们属于同一个层叠上下文中,这时候 stacking2 整体覆盖 stacking1
这时候我们修改一下 stacking1 的 z-index = 2
html
<h2>兄弟都是层叠上下文的</h2>
<div class="container" style="position:relative;background-color: #ddd;height: 50px;z-index:0;">
<!-- 后面的覆盖前面的,显示层叠上下文1 -->
<div class="bg-blue stacking1" style="position:absolute;top: 0px;z-index:2;">层叠上下文1----</div>
<div class="bg-org stacking2" style="position:absolute;top: 0px;z-index:1;">层叠上下文2</div>
<img src="../css/timg.jpg" height="50" width="50" style="position:absolute;top: 0px;z-index:auto;">
</div>
效果图如下:
这时候我们发现 stacking1 整体覆盖 stacking2 那么说明对于同一个层叠上下文下的兄弟层叠上下文,其遵循:
z-index相同的后来居上
z-index不同的谁大谁上
这时候我们是否忘记了 对于子层叠上下文他们属于同一层叠上下文,但是可能不是兄弟元素。那么这时候那?
html
<h2>兄弟都是层叠上下文的</h2>
<div style="position:relative;background-color: #ddd;height: 50px;z-index:0;">
<!-- 虽然层叠上下文1与层叠上下文2 不是兄弟元素了,但是他们拥有一个共同的直系父级层叠上下文 body 所以仍然是 两个层叠上下文进行比较(不是层叠上下文1 与 层叠上下文2的父元素比较 。 所以结果就是 层叠2覆盖层叠1) -->
<div class="bg-blue stacking1" style="position:absolute;top: 0px;z-index:2;">层叠上下文1----</div>
<div style="background-color: #eee;height: 21px;width: 400px;">
<div class="bg-org stacking2" style="position:absolute;top: 0px;z-index:1;">层叠上下文2</div>
</div>
<img src="../css/timg.jpg" height="50" width="50" style="position:absolute;top: 0px;z-index:auto;">
</div>
效果图如下:
这时候还是遵循着上面所说的z-index不同的谁大谁上,而不再会是否是在DOM结构上是兄弟元素(只要遵循在同一个层叠上下文的兄弟层叠上下文)
2. 父子层叠上下文
其实刚才兄弟层叠上下文的栗子就很好
html
<div class="container" style="position:relative;background-color: #ddd;height: 50px;z-index:10;">
<div class="bg-blue stacking1" style="position:absolute;top: 0px;z-index:11;">层叠上下文1----</div>
<div style="background-color: #eee;height: 21px;width: 400px;">
<div class="bg-org stacking2" style="position:absolute;top: 0px;z-index:1;width: 300px;">层叠上下文2</div>
</div>
<img src="../css/timg.jpg" height="50" width="50" style="position:absolute;top: 0px;z-index:auto;">
</div>
效果图如下:
我们知道container是父层叠上下文,其z-index = 10。存在两个子层叠上下文stacking1 其z-index = 11,stacking2 其z-index = 1。
其中还存在父层叠上下文的背景色 #ddd, 父层叠上下文的普通元素 img 和 stacking2的父元素(背景色#eee)。
我们按照上面的层叠等级知道 定位元素 > block块元素 > 父背景色
然后子层叠层叠上下文 z-index > 0 的情况下,哪怕小于父层叠上下文如 stacking2 < container 但是仍然覆盖父元素的普通元素。
如果 z-index = 0 或者 -1 ...情况会如何?
html
<div style="position:relative;background-color: #ddd;height: 50px;z-index:-2;">
<!-- 普通定位元素 < z-index=0的层叠上下文元素stacking1 -->
<div style="background-color: red;height: 21px;width: 500px;position:absolute;top: 0px;"></div>
<div class="bg-blue stacking1" style="position:absolute;top: 0px;width: 200px;color:#fff;z-index:0;">层叠上下文1----</div>
<!-- z-index 为负数的子层叠上下文(z-index小于父层叠上下文) 会被父层叠上下文的背景覆盖 < 父层叠上下文 -->
<div class="bg-blue stacking3" style="position:absolute;top: 0px;width: 300px;color:#fff;z-index:-3;">层叠上下文3----</div>
<div style="background-color: #eee;height: 21px;width: 600px;">
<div>------------------------------------------</div>
<!-- z-index 为负数的子层叠上下文(哪怕z-index大于父层叠上下文) 会被父层叠上下文的背景覆盖 < 父层叠上下文 -->
<div class="bg-org stacking2" style="position:absolute;top: 0px;width: 300px;z-index:-1;">层叠上下文2</div>
</div>
<!-- 普通定位元素 > z-index=0的层叠上下文元素stacking1 -->
<img src="../css/timg.jpg" height="50" width="50" style="position:absolute;top: 0px;z-index:auto;">
</div>
所以我们看出在父子层叠上下文中:
如果子层叠上下文 z-index > 0 ,那么子层叠上下文父覆盖父层叠上下文的背景、普通元素等。
如果子层叠上下文 z-index < 0 , 不管父层叠上下文z-index为多少, 其都小于父层叠上下文的背景(那就跟别谈什么普通定位元素、块元素等);
如果子层叠上下文 z-index == 0 , 那么其就相当于父层叠上下文下的一个普通定位元素,那么就按照7阶层叠水平就行比较了。
那么 z-index : 0 是否就等于 z-index = auto ?
对于父层叠上下文来说 这两个是没有什么差别的,都是看做定位元素按照后来居上的元素在Z轴显示。 但是在实际上其还是有差别的:
z-index:0的定位元素会产生层叠上下文,而z-index:auto的定位元素不会参数层叠上下文,这就对于两个定位元素的子元素产生了影响。
html
<h2>z-index : 0 是否就等于 z-index = auto</h2>
<!-- z-index:auto -->
<div style="position:relative;background-color: #ddd;height: 50px;z-index:-2;">
<!-- box1 没有形成层叠上下文 -->
<div class="box1" style="background-color: #eee;height: 21px;width: 600px;position:absolute;top:0;z-index:auto;">
<div class="bg-org stacking1" style="position:absolute;top: 0px;width: 200px;z-index:2;">层叠上下文1</div>
</div>
<!-- box2 没有形成层叠上下文 -->
<div class="box2" style="background-color: red;height: 21px;width: 600px;position:absolute;top:0;z-index:auto;">
<div class="bg-blue stacking2" style="position:absolute;top: 0px;width: 300px;z-index:1;color: #fff;">层叠上下文2</div>
</div>
<!-- 所以 stacking1 与 stacking2 就是兄弟层叠上下文,那就按照z-index的大小进行比较,所以stacking1 > stacking2 -->
</div>
<!-- z-index:0 -->
<div style="position:relative;background-color: #ddd;height: 50px;z-index:-2;">
<!-- box1 形成层叠上下文 -->
<div style="background-color: #eee;height: 21px;width: 600px;position:absolute;top:0;z-index:0;">
<div class="bg-org stacking1" style="position:absolute;top: 0px;width: 300px;z-index:2;">层叠上下文1</div>
</div>
<!-- box2 形成层叠上下文 -->
<div style="background-color: red;height: 21px;width: 600px;position:absolute;top:0;z-index:0;">
<div class="bg-blue stacking2" style="position:absolute;top: 0px;width: 200px;z-index:1;color: #fff;">层叠上下文2</div>
</div>
<!-- 因为z-index:0 那么box1和box2就形成了层叠上下文,那么box1和box2才是兄弟层叠上下文,而 stacking1 与 stacking2不是兄弟层叠上下文,他们的层叠等级关系是按照其在 container下的父兄弟层叠上下文来决定的 -->
</div>
总结
兄弟层叠上下文间的比较按照:
- z-index不同的 : 大的在上
- z-index相同的 : 后来居上。
父子层叠上下文间的比较, 按照:
z-index > 0 : 子层叠上下文大于父层叠上下文的 定位元素
z-index = 0 : 子层叠上下文就相当于一个普通定位元素,按照7层层叠等级进行比较(注意z-index:0与z-index:auto的区别).
z-index < 0 : 子层叠上下文小于父层叠上下文的背景(那就跟别谈其他的了)
z-index
前面讲了跟多有关z-index的情况,如层叠上下文上z-index>0的时候、z-index=0的时候等等。
介绍z-index
zIndex 的值 auto | integer(整数) | inherit(继承)
定义:一个元素在文档中的层叠顺序,用于确认元素在当前层叠上下文中的层叠级别。
特性:
支持负值 z-index : -1;
支持CSS3 animation 动画
在CSS2.1 一般配合定位元素使用
position : relative | absolute | fixed | sticky
如果定位元素没有发生嵌套
- 后来居上
- 那个大, 那个上
如果发生嵌套
- 祖先优先原则
css3 一些其他属性也能产生层叠上下文
普通元素设置z-index无效