堆叠的半透明盒子的颜色取决于订单?


84

为什么两个堆叠的半透明盒子的最终颜色取决于顺序?

如何使两种情况下的颜色相同?

.a {
  background-color: rgba(255, 0, 0, 0.5)
}

.b {
  background-color: rgba(0, 0, 255, 0.5)
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>


7
我不知道这个问题的答案,但是同一件事在photoshop中也会发生,这是我多年以来作为计算机色彩理论的一部分而接受的东西。我会四处看看是否能找到更多信息。
YAHsaves

11
就其价值而言,对于不是100%透明且从正面照亮的任何事物,在现实生活中也会发生相同的事情。来自前面物体的更多光进入您的眼睛,因此,即使两者都具有50%的透明度,其颜色对最终颜色的影响也更大。
jpa

4
@YAHsaves:0和100的平均值为50(步骤1)。50和150的平均值为100(步骤2)。比较一下:150和0的平均值为75(步骤1)。75和100的平均值为87.5(步骤2)。问题是这三个数字未正确加权。需要同时根据所有数字计算平均值;您不能只一步一步地递归计算平均值。(请注意,平均计算本质上是50%的透明度计算。该计算会针对不同的透明度级别进行更改,但是原理保持不变)
更加平坦

2
经验教训:使用“混合混合模式:乘法”,我将获得一种与堆叠顺序无关的颜色-这就是我最初想要的颜色!我认为@Moffens答案对于面临相同问题的任何其他用户最有用。但是Temani Afif的解释实际上适用于我的问题,并描述了HTML为什么以另一种方式表现(它模仿物理光通过半透明箔片的传播),所以绿色的勾号出现在他身上。
rmv

Answers:


101

仅仅因为在两种情况下,颜色的组合都不一样,这是由于顶层的不透明度如何影响底层的颜色。

对于第一种情况,您会在顶层看到50%的蓝色和50%的透明。通过透明部分,您可以在底层看到50%的红色(因此,我们总共只能看到25%的红色)。第二种情况的逻辑相同(红色的50%蓝色的25%);因此您会看到不同的颜色,因为在两种情况下我们的比例都不相同。

为避免这种情况,两种颜色的比例必须相同。

这是一个示例,可以更好地说明和展示如何获得相同的颜色:

在顶层(内部跨度)中,我们具有0.25不透明性(因此,我们具有第一种颜色的25%和透明性的75%),然后对于底层(外部跨度)中,我们具有0.333不透明性(因此,我们具有1/3的不透明性)75%=颜色的25%,其余为透明)。我们在两个图层中所占的比例相同(25%),因此即使颠倒图层顺序,我们也会看到相同的颜色

.a {
  background-color: rgba(255, 0, 0, 0.333)
}

.b {
  background-color: rgba(0, 0, 255, 0.333)
}

.a > .b {
  background-color: rgba(0, 0, 255, 0.25)
}
.b > .a {
  background-color: rgba(255, 0, 0, 0.25)
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>

附带说明,白色背景也影响颜色的呈现。它的比例是50%,这将得出100%的逻辑结果(25%+ 25%+ 50%)。

您可能还会注意到,如果顶层的不透明度大于,0.5因为第一层的不透明度大于50%,第二层的不透明度小于50%,那么两种颜色的比例就不可能相同一:

常见的琐碎情况是顶层具有opacity:1使顶层颜色比例为100%的图层;因此它是不透明的颜色。


对于这里的更准确和精确的解释是用于计算我们两个层的组合后看到的颜色式REF

ColorF = (ColorT*opacityT + ColorB*OpacityB*(1 - OpacityT)) / factor

ColorF是我们的最终颜色。ColorT / ColorB分别是顶部和底部的颜色。 opacityT / opacityB分别是为每种颜色定义的顶部和底部不透明度:

factor由如下公式定义OpacityT + OpacityB*(1 - OpacityT)

显然,如果我们切换两个图层,factor则不会改变(它将保持不变),但是我们可以清楚地看到每种颜色的比例都会改变,因为我们没有相同的乘数。

对于我们最初的情况,这两种情况都是0.5如此,因此我们将有:

ColorF = (ColorT*0.5 + ColorB*0.5*(1 - 0.5)) / factor

如上所解释,顶部颜色的比例为50%(0.5),底部颜色的比例为25%(0.5*(1-0.5)),因此切换图层也会切换这些比例。因此我们看到了不同的最终颜色。

现在,如果我们考虑第二个示例,我们将有:

ColorF = (ColorT*0.25 + ColorB*0.333*(1 - 0.25)) / factor

在这种情况下,我们必须0.25 = 0.333*(1 - 0.25)切换两层无效。因此颜色将保持不变。

我们还可以清楚地识别出一些琐碎的案例:

  • 当顶层opacity:0的公式等于ColorF = ColorB
  • 当顶层opacity:1的公式等于ColorF = ColorT

23
@ChrisHappy无法解决问题;)正在解释..有时解释比解决问题要好
Temani Afif

即使您将div彼此分开并定位:将它们绝对堆叠,仍然会出现问题。
YAHsaves '18

1
@YAHs即使我们使用多个背景或使两种颜色相互重叠的任何事物(是否使用绝对位置),也会出现问题()
Temani Afif

5
如果要添加TLDR,可能是它们是乘法的而不是加法的。
卡拉米里尔'18

2
@Caramiriel:“可乘”仍不能解释为什么该运算不是可交换的。
埃里克·杜米尼尔

41

您可以使用css属性,mix-blend-mode : multiply (有限的浏览器支持

.a {
  background-color: rgba(255, 0, 0, 0.5);
  mix-blend-mode: multiply;
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
  mix-blend-mode: multiply;
}

.c {
  position: relative;
  left: 0px;
  width: 50px;
  height: 50px;
}

.d {
  position: relative;
  left: 25px;
  top: -50px;
  width: 50px;
  height: 50px;
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>

<div class="c a"></div>
<div class="d b"></div>

<div class="c b"></div>
<div class="d a"></div>


6
此列表中的几乎所有“可交换”颜色混合模式都可以解决问题。
Salman A

有趣的是,这适用于Chrome,但不适用于Edge(最新的Windows 10更新)。
洪井

3
@rmv为什么您会期望除叠加/正常以外的其他功能?什么是如果你预期的颜色定位在一个红色的盒子前面的不透明的蓝色盒子?它将是蓝色而不是红色或蓝色和红色的功能。
Salman A

1
@Moffen完美答案,但是您能否添加一个解释说明为什么这样有效,为什么原始代码无效?
Bergi '18年

1
@rmv:最接近“正常”混合模式的是实际上是油漆混合。例如,如果您使用一些白色油漆,将其一半替换为红色油漆,然后将所得的一半粉红色油漆替换为蓝色油漆,您将得到带蓝色的紫色(白色25%,红色25%,蓝色)。如果您使用相同的白色涂料,但首先用蓝色替换一半,然后用红色替换一半,则最终将得到带红色的紫色(25%白色,25%蓝色,50%红色)。
Ilmari Karonen

22

您正在按以下顺序混合三种颜色:

  • rgba(0, 0, 255, 0.5) over (rgba(255, 0, 0, 0.5) over rgba(255, 255, 255, 1))
  • rgba(255, 0, 0, 0.5) over (rgba(0, 0, 255, 0.5) over rgba(255, 255, 255, 1))

您会得到不同的结果。这是因为使用非交换3的普通混合模式1,2将前景色与背景色混合。由于它不是可交换的,因此交换前景色和背景色将产生不同的结果。

1混合模式是一种接受前景色和背景色,应用某些公式并返回所得颜色的功能。

2给定背景和前景色两种颜色,普通混合模式仅返回前景色。

3如果更改操作数的顺序不更改结果,则操作是可交换的,例如加法是可交换的(1 + 2 = 2 +1)而减法不是(1-2≠2-1)。

解决方案是使用可交换的混合模式:以任意顺序为同一对颜色返回相同颜色的混合模式(例如,乘以混合模式,将两种颜色相乘并返回结果颜色;或加深混合模式,其返回两者的深色)。


为了完整起见,以下是计算合成色的公式:

αs x (1 - αb) x Cs + αs x αb x B(Cb, Cs) + (1 - αs) x αb x Cb

与:

Cs:前景色的颜色值
αs:前景色的alpha值
Cb:背景色的颜色值
αb:背景色的alpha值
B:混合功能


8

有关发生的情况的说明,请参阅Temani Afif的答案。
作为一种替代解决方案,您可以采用一个跨度,a例如,将其定位并在内部将其赋予较低的z索引b。然后,堆叠将始终相同:在第一行的b顶部绘制,a在第二行的a下方绘制b

.a {
  background-color: rgba(255, 0, 0, 0.5);
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
}

.b .a {position:relative; z-index:-1;}
<span class="a"><span class="b">     Color 1</span></span>
<span class="b"><span class="a">Same Color 2</span></span>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.