修复 IE 中带有下拉列表的重叠图层






4.30/5 (20投票s)
本文要讨论的问题只出现在 Internet Explorer 中。当一个绝对定位的图层(div)被下拉菜单或某些 ActiveX 组件覆盖时,z-index 样式表属性不起作用,图层显示在这些对象下方。
引言
本文要讨论的问题只出现在 Internet Explorer 中。当一个绝对定位的图层(div
)被下拉菜单或某些 ActiveX 组件覆盖时,z-index 样式表属性不起作用,图层显示在该对象下方。
Web 开发人员经常使用绝对定位的图层来创建导航元素(如下拉菜单),显示消息,甚至构建整个页面。那么,有什么解决方法呢?
方法一:隐藏页面上的所有下拉菜单
第一种方法的思路很简单——隐藏页面上的所有下拉菜单。如果没有下拉菜单,就不会出现这个问题。没错,但这不适用于 ActiveX 组件。
要隐藏所有下拉菜单,我们可以使用客户端脚本代码。例如,使用 JavaScript,我们可以通过循环遍历所有元素列表来查找表单上的所有下拉菜单。
// looping through all forms on the page
for (f = 0; f < document.forms.length; f++)
{
var elements = document.forms[f].elements;
// looping through all elements on certain form
for (e = 0; e < elements.length; e++)
{
if (elements[e].type == "select-one")
{
elements[e].style.display = 'none';
}
}
}
第一个循环用于表单数组,第二个循环用于某个表单上的每个元素。此外,对于每个元素,我们检查其类型,如果类型等于“select-one”,我们将display
属性更改为“none
”,以便隐藏该元素。最后,添加一个显示图层的代码块,我们就得到了ShowLayer()
函数,我们可以用它来显示页面上的图层。
function ShowLayer() {
// hide all dropdowns on the page
// looping through all forms on the page
for (f = 0; f < document.forms.length; f++)
{
var elements = document.forms[f].elements;
// looping through all elements on certain form
for (e = 0; e < elements.length; e++)
{
if (elements[e].type == "select-one")
{
elements[e].style.display = 'none';
}
}
}
// show layer
var layer = document.getElementById('layer');
layer.style.display = 'block';
}
要隐藏图层并再次显示下拉菜单,我们需要执行类似的操作,但顺序相反。此逻辑将封装在HideLayer()
函数中。
function HideLayer() {
// hide all dropdowns on the page
for (f = 0; f < document.forms.length; f++)
{
var elements = document.forms[f].elements;
for (e = 0; e < elements.length; e++)
{
if (elements[e].type == "select-one")
{
elements[e].style.display = 'block';
}
}
}
// hide layer
var layer = document.getElementById('layer');
layer.style.display = 'none';
}
在我看来,这种解决方案的主要缺点是在脚本隐藏所有下拉菜单时会更改用户界面,这可能会让用户感到困惑。此外,使用这种方法,我们可能会隐藏那些并没有覆盖图层但具有重要功能的下拉菜单,而用户在图层显示时可能需要使用这些功能。让我们看看方法二。
方法二:使用 IFRAME
这种方法的思路是使用IFRAME
。此元素覆盖表单的所有其他元素以及 ActiveX 组件。但这种方法的巧妙之处在于我们可以为其设置 z-index!因此,我们可以创建一个在下拉菜单和绝对定位图层之间的分隔图层。让我们来看这个简单的例子(省略号部分我放了一个我在方法一中使用过的带有下拉菜单的表单)
<html>
<head>
<title>Method Two</title>
<style>
#layer {
position: absolute;
top: 10px;
left: 100px;
width: 220px;
height: 100px;
border: 1px solid black;
background-color: #e4e4e4;
padding: 10px;
z-index: 11;
}
#iframe {
position: absolute;
top: 10px;
left: 100px;
width: 222px;
height: 102px;
z-index: 10;
}
</style>
</head>
<body>
<form>
<iframe id="iframe" frameborder="0"></iframe>
<div id="layer">
This is absolutely positioned layer.
</div>
...
</form>
</body>
</html>
如果您在 IE 中打开此 HTML 页面,您会看到下拉菜单将在图层下方。这是因为我在表单元素(如下拉菜单和图层)之间放置了第三个图层。我将其 z-index 设置为 10,而图层的 z-index 设置为 11。我还将宽度和高度设置为与绝对定位图层完全相同,因此它对用户隐藏,只是起到了隐藏其下方所有内容的作用。
让我们修改方法一中示例中的函数以与IFRAME
一起使用。
function ShowLayer() {
// show layer
var layer = document.getElementById('layer');
layer.style.display = 'block';
// show IFRAME
var iframe = document.getElementById('iframe');
iframe.style.display = 'block';
iframe.style.width = layer.offsetWidth;
iframe.style.height = layer.offsetHeight;
iframe.style.left = layer.offsetLeft;
iframe.style.top = layer.offsetTop;
}
function HideLayer() {
// hide IFRAME
var iframe = document.getElementById('iframe');
iframe.style.display = 'none';
// hide layer
var layer = document.getElementById('layer');
layer.style.display = 'none';
}
ShowLayer
函数根据图层属性设置IFRAME
的宽度、高度、左边距和上边距值。我们不需要在下拉菜单图层的样式表中设置这些值。
方法三:将 SELECT 替换为 SPAN
Volkan.ozcelik 在他的文章 Modal Dialog – enhanced 中发布了一个有趣的方法。他建议使用替换来避免“渗漏”。在打开新的图层之前,JavaScript 函数会搜索整个 HTML 文件并将所有下拉菜单替换为SPAN
标签。使用 CSS,我们可以使SPAN
看起来几乎像一个SELECT
,这样表单视图只会稍作更改,不会像方法一那样隐藏所有下拉菜单时那样让用户感到困扰。
结论
我认为第一种方法没有任何优势。它对 ActiveX 组件无效,并且当 JavaScript 隐藏页面中的所有下拉菜单时会让用户感到困扰。第二种方法对下拉菜单和 ActiveX 组件都有效,并且不会更改SELECT
。第三种方法仅对下拉菜单有效,并且会稍微更改表单的视图。此外,由于所有SELECT
都将被替换为SPAN
,因此在图层显示时用户无法使用表单。
前两种方法的示例可以在源文件中找到。关于方法三的示例,请参考 Modal Dialog – enhanced 文章。