利用z-index,可以改变元素相互覆盖的顺序,有较高z-index值的元素比z-index值较低的元素离读者更近。也就是说有较高z-index值的元素会覆盖其他元素。
① 如果不对节点设定position属性,位于文档流后面的节点会覆盖前面的节点。比如
<div id="a">a</div> <div id="b">b</div>
② 如果将position设为relative,absolute或者fixed,这样节点会覆盖没有设置position属性值或者属性值为static的节点
<div id="a">a</div> <div id="b" style="position:relative">b</div>
③ 如果所有节点都定义了position的值且值都不为static,并且未指定z-index值,那么文档流后面的依然要覆盖前面的
<div id="a" style="position:absolute;top:0;">a</div> <div id="b" style="position:absolute;top:0;">b</div>
由①②③可知,正常情况下即没有设定z-index值时,文档流后面的节点比文档流前面的节点层级高,设定了position的值(relative/absolute/fixed)的节点比没有设定position值或者值为static的节点层级高。比如:
<div id="a"> <div id="a-1" style="position:relative;">a-1</div> </div> <div id="b">b</div>
b位于文档流a之后,所有b会覆盖a,而a-1又由于设定了position的值,所以a-1会覆盖b。
在不使用position属性的节点上使用z-index属性,z-index不会改变叠放顺序。所以要利用z-index来改变叠放的顺序,节点上必须有position属性。
z-index的值可以取负数,0,正数,auto。那么什么时候z-index的值为auto呢?对于使用了position属性但是没有用z-index的值的节点,在IE6/7中,z-index默认为0,而其他浏览器默认是auto。z-index为0和auto的区别是:z-index为0的节点要参与层级比较,而z-index为auto的节点不参与层级关系比较。
④ 所有节点都使用了position属性(relative/absolute/fixed),z-index为0的节点与z-index为auto的节点在同一层级内没有高低之分,而z-index大于等于1的节点高于z-index为0或者auto的节点,z-index为负数的节点低于z-index为0或者auto的节点。
<div id="a" style="position:absolute;z-index:2;">a</div> <div id="b" style="position:absolute;z-index:0">b</div> <div id="c" style="position:absolute;">c</div> <div id="d" style="position:absolute;z-index:-1;">d</div>
c没有设定z-index的值,所以z-index的值为auto,a的z-index的值为2大于b,c,d,所以在最上面,而b的z-index的值为0,虽然在同一层级内b,c没有高低之分,但是在文档流中c位于b之后,所以b在c的下面,d的z-index为-1,所以在最下面。
一旦为一个节点指定了z-index(不为auto),该节点就会建立自己的局部叠放上下文。意味着,节点的所有后代相对于该节点(指定了z-index)都有其自己的叠放顺序。
⑤ 如果a,b节点定义了position:absolute,a节点的z-index比b节点大,那么a节点的所有子节点会覆盖b节点以及子节点。比如:
<div id="a" style="position:absolute;z-index:2"> <div id="a-1" style="position:absolute;z-index:1">a-1</div> </div> <div id="b" style="position:absolute;z-index:1"> <div id="b-1" style="position:absolute;z-index:3">b-1</div> </div>
由于a的z-index大于b的z-index的值,所以a会覆盖b,a的子节点a-1也会覆盖b,即使b的子节点b-1的z-index值为3比a-1大。
为某个节点指定了z-index值,且该值不为auto,那么该节点会建立局部叠放上下文,后代节点会参照该节点。但是如果某个节点设定了position的值,但是未设定z-index属性时,即z-index在IE6/7中为0,其他浏览器中为auto。当z-index为auto时,该节点不会建立局部叠放上下文,那么该节点的后代节点该怎么办呢?由此引出定位树的概念。
浏览器在渲染DOM节点时,除了生成DOM树之外,还会根据DOM树种的定位元素(position不为static)生成定位树。
⑥ 根据定位树来确定层级关系,z-index 为 auto 的节点不参与层级关系的比较, 由向上遍历至此且 z-index 不为 auto 的节点来参与比较。比如:
<div id="a" style="position:absolute;z-index:2"><div id="a-1" style="position:relative;z-index:100"> a-1 </div> </div> <div id="b"><div id="b-1"><div id="b-1-1" style="position:relative;z-index:10;">b-1-1</div> </div> </div> <div id="c" style="position:absolute"><div id="c-1"><div id="c-1-1"><div id="c-1-1-1" style="position:absolute;z-index:5">c-1-1-1</div> </div> </div> </div>
在除IE6/7的浏览器中,c的z-index值为auto,所以它不参与层级比较,它也不为后代建立层叠上下文,后代元素逐级寻找z-index不为auto的最近的祖先元素。此次的层级关系为:
- a>c>b 因为a的z-index为2,c的z-index为auto,文档流中c在b的后面,所以c>b
- b-1-1>a 因为b-1-1逐级向上寻找z-index不为auto的祖先节点,最后它与a在同一个层叠上下文中,且b-1-1的z-index为10,所以b-1-1层级大于a
- a<c-1-1-1<b-1-1 因为c-1-1-1逐级向上寻找z-index不为auto的祖先节点,最后它与a、b-1-1在同一个层叠上下文中,且c-1-1-1的z-index为5,所以它大于a,小于b-1-1
在IE6/7的浏览器中,c的z-index值为0,当z-index为0,会参与层级关系比较,会建立自己的局部层叠上下文。此时的层级关系为:
- a>c>b a的z-index为2,c的z-index为0,所以a>c
- b-1-1>a>c
- c-1-1-1<b-1-1 因为c的z-index为0,c<b-1-1,c建立自己的局部层叠上下文,所以c-1-1-1<b-1-1
注意:1.IE6/7 下 position 不为 static, 且 没有z-index属性时 ,z-index 为 0, 除此之外的浏览器 z-index 为 auto。
2.z-index为0会参与层级比较,建立局部层叠上下文,影响子节点的层级。z-index为auto不参与层级比较,不会建立局部层叠上下文,子节点逐级向上寻找最近的z-index不为auto的节点。
参考文章:http://www.neoease.com/css-z-index-property-and-layering-tree/comment-page-1/
http://www.neoease.com/css-z-index-dom-tree-to-layering-tree/