神奇的z-index

z-index问题很常见,在IE下会有莫名其妙的BUG,自己找了几篇文章,仔细研读了一下。这篇文章很大一部分是对这几篇英文文章的翻译,但结合学到的东西,加上自己的理解,也就成了此文。

没有添加z-index属性:

  • 叠加顺序按照节点在html中出现的顺序排列,后出现的在上面(一般原则)
  • 节点有定位时,仍然遵循上面的原则,但定位元素处于非定位元素上层(一般原则)
  • 各个节点当中,当既有定位节点,又有浮动节点的时候:

    IE6,7,8下(更高版本的IE没有测试,大家可以将下面那个jsfiddle放在IE下亲自运行试一下):仍然遵从上面的一般原则,但是定位元素的层级要高于浮动元素的层级,见下图

    ie下的显示图

    非IE下: 仍然遵从上面的一般原则,但是没有但是(哈哈)

添加了z-index属性:

z-index属性只能添加到定位元素上,非定位元素加了也没有用,一个定位元素如果没有显式地设置z-index值,那么默认值为0。z-index值越高,处于的层级越高。

  • DOM节点当中,各个元素都是兄弟关系时:
  • DOM节点中有父子关系时:(这里有一个stacking context的概念)

对于stacing context ,我的理解是,当一个元素是一个定位元素并且设置了z-index值的时候,它就会有一个给它层级的上下文。定位元素会拿离自己最近的并且有z-index属性的父元素作为自己的stacking context.

一个拼爹的时代开始了:

#1,#2,#3是并列关系,而且都是定位元素,所以它们的层级由z-index决定,#1>#3>#2。

#4的z-index是6,#1的z-index是5,但#1却站在了#4头上,这是为什么呢?

因为#4的爹#3不行,z-index只有4。

#5的z-index是1,#2的z-index是2,#5却站在了#2头上,为啥呢?

同理,#5的爹#3牛逼,z-index是4,而#2只有2。

同级下的元素相比较就不能拼爹了,而是要看各自的z-index了。

看#3里面的三个子元素#4,#5,#6,#5<#6<#4,并且爸爸一向是有牺牲精神的,可以让儿子当马骑,儿子的层级永远是在老爸之上的。

看几个例子:

Dom结构是这样的:

#1     
    #2
#3     
    #4

都有定位,但没有指定z-index,也就是说z-index都是0

示意图

很简单,层次关系按照文档流排列。

但当#2的z-index设置成1的时候,IE6,7下的表现与其他浏览器有些不同:

大多数浏览器是这样的:

分析一下:#2有z-index值并且它是#1的子元素,但是#1没有z-index值,#2也就只好拿root(html)当stacking context了,其他元素都没有z-index值,所以,#2的层级就最高了。

但在IE6,7下还是这样,IE8和现代浏览器渲染相同:

ie下的示意图

分析一下:可见IE6,7的立场相当坚定,一个元素的stacking context就是他的直接父元素,不论父元素有没有z-index属性,没有默认是0,老爸条件相同时,儿子再怎么能耐都不行!

当#2,#4都设置z-index值时:

IE6,7立场仍然坚定

ie下的示意图

其他浏览器:

显得浏览器下的示意图

这时,#2,#4的stacking context都是root,这就要比z-index值了,#4>#2。

再看下面的例子,DOM结构还是上面的结构:

根据上面讲到的stacking context的知识我们判断,#2的stacking context是root,#4的stacking context是#3,虽然#2的z-index:2,#4的z-index:10,但#2的stacking context厉害啊,root啊,所以。。。#4就被#2和谐了,哈哈。

但在IE6,7下却有不同的结果

ie下的示意图

IE6,7仍然坚挺,#2的爹不行,所以#3会骑在#2头上,#4就更不用说了。

z-index的问题还是要变通着处理,有时可以改变下dom结构解决复杂的z-index问题。关于更多的z-index介绍请参照Mozilla Developer Network


blog comments powered by Disqus