IE 6和IE 7的Z-Index问题

21

http://madisonlane.businesscatalyst.com

我想让 div#sign-post 显示在 div#bottom 的上方。在除了 IE6 和 IE7 之外的所有浏览器中,这个效果都很好。有人能看出问题在哪里吗?

此外,IE6 在 div#bottom 的顶部额外显示了 198 像素。


具有讽刺意味的是,它在IE8中运行良好。 - Chris
7个回答

152
大部分回答都是错误的;有些可以工作,但原因并不是他们所说的。以下是一些解释。
下面是 规范 规定 z-index 应该如何工作:
- 您可以为任何元素设置 z-index 值;如果没有设置,则默认为 auto。 - 具有不同于默认 static 的 position 属性的定位元素(即具有 z-index 不同于 auto 的元素)会创建一个新的层叠上下文。层叠上下文是重叠的“单元”;一个层叠上下文要么完全在另一个上面(也就是说,第一个元素的每个元素都在第二个元素的上面),要么完全在其下面。 - 在同一层叠上下文中,比较元素的堆栈级别。具有显式 z-index 值的元素具有该值作为堆栈级别,其他元素从其父级继承。具有更高堆栈级别的元素显示在顶部。当两个元素具有相同的堆栈级别时,通常在 DOM 树中后出现的元素会绘制在顶部。(如果它们具有不同的 position 属性,则应用更复杂的规则。)
换句话说,当两个元素都设置了z-index时,为了决定哪一个显示在顶部,您需要检查它们是否有任何已定位的父元素也设置了z-index。如果没有或者父级是相同的,则具有更高z-index的元素获胜。如果有,则需要比较父级,子元素的z-index是无关紧要的。
因此,z-index决定了元素与其“堆叠父级”(最近的祖先具有设置为relativeabsolutefixedpositionz-index)的其他子元素相比如何放置,但与其他元素比较无关;计数的是堆叠父级的z-index(或可能是堆叠父级的堆叠父级等)。在典型文档中,您仅在几个元素(如下拉菜单和弹出窗口)上使用z-index,其中没有一个包含另一个,所有具有z-index的元素的堆叠父级都是整个文档,您通常可以认为z-index是全局的、文档级别的排序。
IE6/7与其他浏览器的一个根本区别在于,定位元素会创建新的层叠上下文,无论它们是否设置了z-index。由于你通常会给绝对定位的元素或其相对定位的父元素或近祖元素分配z-index值,这意味着你的z-index元素根本不会被比较,而是会比较它们的定位祖先元素,因为它们没有设置z-index,所以文档顺序将占主导地位。
解决方法是找出哪些祖先元素实际上被比较,并给它们分配一些z-index来恢复你想要的顺序(通常是反向文档顺序)。通常使用JavaScript来完成此操作 - 对于下拉菜单,可以遍历菜单容器或父菜单项,并为它们分配1000、999、998等z-index。另一种方法:当弹出窗口或下拉菜单变为可见时,找到所有相对定位的祖先元素,并给它们一个具有非常高z-index的“on-top”类;当它再次变为不可见时,删除这些类。

4
谢谢你为我解决了一个谜团! :) 我一直与元素排序有问题,每次都觉得自己在用黑魔法来让它正常工作。 - Jason Sperske
1
在什么情况下这种方法(将z-index添加到相对父元素)不起作用,是否有其他解决方法? - DEfusion
1
@DEfusion:IE6还有一个与垂直定位相关的bug;一些元素(例如<select>或Flash)似乎在文档之外,而且没有办法通过z-index将东西放在它们上面。通常通过在它们和弹出窗口之间放置一个iframe来解决这个问题。 - Tgr
9
感谢!对于需要始终置于顶部的下拉或弹出式小部件,使用jQuery很容易解决。在打开小部件时调用$(myWidget).parents().addClass('on-top'),在关闭它时调用$(myWidget).parents().removeClass('on-top')。 - RMorrisey
1
@RMorrisey 很好的解释,我之前不知道这个。jQuery 代码片段对我也起作用了。谢谢! - Ricardo Zea
显示剩余7条评论

20

同意验证器的评论 - 验证通常是有帮助的。但如果不行,以下是一些在IE中操作z-index的要点:

1)你正在操作其z-index的元素应该处于同一级别上,即你应该设置#bottom和#body的z-index。

如果不可行,那么

2)除非你将要应用它们的元素具有 position:relative 属性,否则IE有时不会正确地应用z-index。尝试将该属性应用于#bottom 和 #body(或 #signpost)。

让我知道它的效果如何。

Darko


我相信这是由于已知的错误引起的,通过在样式表中添加“position:relative”来修复。 - David Hanak
4
这种行为是因为IE6/7会为每个设有position:relative属性的元素开启一个新的层叠上下文。http://brenelz.com/blog/squish-the-internet-explorer-z-index-bug/ - hitautodestruct

4

我刚遇到了这个问题,根据Quirksmode的建议,解决方法是给你尝试设置的节点的直接父节点分配一个自己的z-index,该z-index应小于你尝试设置的节点的z-index。以下是一个快速示例,适用于IE6。

<html>
  <head>
    <style type="text/css">
      #AlwaysOnTop {
        background-color: red;
        color: white;
        width: 300px;
        position: fixed;
        top: 0;
        z-index: 2;
      }
      #Header {
        color: white;
        width: 100%;
        text-align: center;
        z-index: 1;
      }
    </style>
  </head>
  <body>
    <div id="Header">
      <div id="AlwaysOnTop">This will always be on top</div>
    </div>
    <div id="Content">Some long amount of text to produce a scroll bar</div>
  </body>
</html>

2
这是因为它将#Header放置在#Content的上方(它可能是一个定位元素)。#Header#AlwaysOnTop之间的z-index关系是无关紧要的。有关详细信息,请参见我的答案。 - Tgr

1

欢迎,我已经解决了这个问题:

.header { 
    position: relative;
    z-index: 1001;
}
.content {
    position: relative;
    z-index: 1000;
}

0

唯一可靠的解决方案是将顶部元素放在代码下面,然后使用绝对定位将它们推到其他内容上方。

例如:WordPress: 将导航放在页脚文件中,但仍在页面包装器内。

这也可能为搜索引擎带来一些优势,因为它们可以直接从内容开始,而不必先爬行菜单...

更新: 我需要更正自己。虽然将元素放在下面然后推上去仍然是最简单的方法,但在某些情况下,这不是在合理时间内实现的。然后您必须确保每个父元素都具有某种定位和有意义的z-index。然后z-index应该再次在IE7中起作用。


0
看起来你的HTML代码有些格式不正确。我试着数了一下,也许我数错了开标签和闭标签的数量,但是div#container好像没有关闭。尝试通过验证器(例如W3C的HTML验证器或其他工具)运行你的页面,并修复一些错误。这在过去帮助过我解决类似的问题。祝你好运!

0

我最近遇到了一个正在进行的问题:无法在一个图层之上显示另一个图层。在我的情况下,我是通过Javascript编程创建了两个图层,一个用于显示自定义控件,另一个用于在其后创建全屏图层。Firefox没问题,但IE总是将全屏图层显示在其他所有图层的顶部。

在浏览网络上的众多建议之后,我最终让它起作用的唯一方法是从两个图层中删除position:属性,并微调margin-top:属性,直到我得到满意的结果。

有点混乱,但它能够工作,等到IE 8解决所有当前的错误之前都会很好......


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接