在浏览器中,不透明度和z-index哪个优先级更高?

69

我在JavaScript中编写了一个“弹出窗口”,遇到了一个有趣的问题:

Cropped screenshot demonstrating strange stacking behavior

即使我希望隐藏该部分,弹出窗口下面的海军蓝色正方形仍然可见。因为弹出窗口是在正方形之后添加的,所以它应该处于顶部。

正方形的CSS opacity 属性为 0.3。根据我的尝试,似乎从区间 (0,1) 中的每个数字都会产生相同的结果。如果我将其更改为 1,那么它就会按预期行事(即弹出窗口下的部分被隐藏)。

我已经尝试将正方形的 z-index 属性设置为 10,将弹出窗口的设置为 100,但没有改变任何东西。

我错过了什么?为什么正方形的一部分被显示出来?

测试的浏览器:

  • Firefox 3.6.x
  • Chrome 4

我猜这可能是一个错误/未实现的功能。然而,由于我不太了解CSS,我认为我不适合回答它。其他浏览器是否也以相同的方式显示?你使用的是什么浏览器? - Maciej Piechotka
弹出窗口的所有元素(版本、PosX、PosY等)是否都具有“z-index: 100;”或“z-index: inherited;”? - Cipi
2
我曾经遇到过同样的问题。我认为这是$browser(火狐浏览器?)中的一个错误。 - knittl
我的一般观点是,除非绝对必要,设计师不应该使用不透明度。我认为有些无知的设计师在使用“不透明度”作为选择他们想要的颜色(也许更浅或更柔和)的方式,而没有意识到不透明度参数具有奇怪的副作用,并且你可以仅使用RGB值选择任何颜色,而不需要不透明度。 - PJ Brunet
8个回答

74

这不是一个 bug,实际上这正是它的预期行为。由于层叠上下文的详细描述没有提及此事,因此可能有点令人困惑。但是,视觉格式模块链接到颜色模块,可以在其中找到这个特定的注意点(强调我的):

由于透明度小于 1 的元素是由单个离屏图像合成的,因此其外部内容不能在 z-order 中对其内部内容之间进行分层。出于同样的原因,对于任何透明度小于 1 的元素,实现必须创建一个新的层叠上下文。如果透明度小于 1 的元素没有定位,则实现必须以与其父层叠上下文中使用的相同层叠顺序绘制所创建的层,在其父层叠上下文中。如果透明度小于 1 的元素被定位,则“z-index”属性的应用方式如[CAS21]中所述,只是“auto”被视为“0”,因为总是会创建新的层叠上下文。有关层叠上下文的更多信息,请参见[CAS21]的第9.9节和附录E。本段规则不适用于SVG元素,因为SVG具有自己的呈现模型([SVG11]第3章)。


18
即使它是“应该如何工作”,对于更多的人来说,这仍然是非常违反直觉的。我认为这是规范中的缺陷。这里有一个示例可以操作:http://jsfiddle.net/WzvLU/1/ - Luke
2
@Luke 欢迎来到网络世界,在这里,业内最糟糕的人制定规则。只需看看属性名称。你想要垂直对齐,我们称之为 align-items;你想要水平对齐,我们称之为 justify-items。 - atilkan
5
我认为这种奇怪的行为是由于行为未明确规定且与浏览器实现方式(2003规范2008规范中明确定义了此行为的规范)匹配有关。至于 align-items 等属性,它们被命名为这样是因为它们不一定被锁定在一个轴上。也就是说,如果另一个属性发生改变,该属性可以保持不变但应用于不同的轴。(Tab/fantasai做了一些使名称在规范中标准化的出色工作)。 - 0b10011
如果你无法简单地解释它,那说明有些问题。为什么要谈论毫无逻辑的事情呢?我们为什么要接受这种错误。这是不对的。 - atilkan
@atilkan,你能简单地解释一下数学吗?我不确定。但是没有比这个领域更准确和正确的了。小心你扭曲的逻辑。也许你无法理解其中的原因。 - Thomas

23

问题不是opacityz-index更重要,而是z-index相对于它们的堆叠上下文(请参见CSS2规范中的z-index)。

换句话说,z-index仅在定位祖先的上下文中起作用(无论是相对、绝对还是固定定位)。要解决问题,您需要为同时包含弹出窗口和导航正方形的元素添加position:relative;,并可能将其添加到z-index:1;。根据您的截图,它很可能是顶部元素,例如包装器div。


5
实际上,这确实与“不透明度”有关。请参见http://www.w3.org/TR/css3-color/#transparency--特别是“...任何不透明度小于1的元素都必须创建一个新的堆栈上下文...” - 0b10011
position: relative 的修复方法对我很有效!谢谢 Guillaume Esquevin。 - Matías Cánepa

9

针对两个元素(例如div)的解决方法:将顶部元素的不透明度设置为0.99,这样两个元素的顺序就会重新建立。

opacity: 0.99;

7

一个替代使用不透明度的方法是使用透明颜色(带有 alpha 值)。

因此,可以使用透明颜色:

{
    background: gray;
    opacity: 0.5;
}

您可以尝试:

{
    background: rgba(128,128,128,0.5);
}

虽然不完全相同,但我之前也遇到了你所描述的问题,按照上述方法解决了。


1

这个问题可能需要示例代码进行调试。

您可以在包围所有编辑器对象的 DIV 中添加 overflow:hidden,以及可能的 position:relative,尝试强制元素仅在该 DIV 中绘制,例如:

<div style="overflow: hidden; position: relative">
    (Editor object buttons go here)
</div>

作为最后的办法,你也可以尝试在两个元素之间加入一个iframe来阻止它们渗透。

0
你可以尝试使用 !important 来设置弹出窗口的 DIV,这样在应用新的样式或类时,样式不会发生变化。
background-color: white !important;
z-index: 100 !important;
opacity: 1.0 !important;

接下来,创建新的CSS类:

.PopupElement
{
 z-index: inherited;
 opacity: inherited;
}

并为窗口中的所有元素添加类,例如:

<input value="posx" class="some_class PopupElement"/>

我猜这应该可以工作,因为据我所知,在应用CSS属性时没有优先级。=)


0

我曾经遇到过同样的问题。使用rgba而不是color/opacity解决了我的问题。在Bootstrap框架中使用LESS,fade()函数为我完成了转换。


1
我认为这是最好的建议!对我来说,这个很有效:background-color: rgba(20,20,20, 0.7); 这个也很好用:background-image: linear-gradient(to bottom, rgba(0,0,0,0.8) , rgba(50,50,50,0.5)); - rick-rick-rick

0

虽然@Guillaume Esquevin已经给出了很好的答案,但我想进一步扩展一下,以防有人忽略什么是堆叠上下文(就像我一样)。

正如您可以在这里阅读到的那样,有些东西称为堆叠上下文,它指的是共享父级的一组元素,在堆栈中一起移动。例如,可能是一个div和其所有子元素。

有三种方法可以创建堆叠上下文:在文档的根部(html元素),通过定位父元素以及将父元素的不透明度更改为低于1。

然后,如果您有一个不透明度低于1的div,并且希望此div的某个同级元素出现在其后面(以及其子元素),则可以通过将其位置设置为相对或更改其不透明度来在此同级元素上创建新的堆叠上下文。


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