堆叠的半透明盒子的颜色取决于订单?
Color of stacked semi-transparent boxes depends on order?
为什么两个堆叠的半透明盒子的最终颜色取决于顺序?
我怎样才能在两种情况下得到相同的颜色?
.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>
仅仅是因为在这两种情况下,由于 top 层的不透明度如何影响 bottom[=99] 的颜色,颜色组合并不相同=]层.
对于第一种情况,您会在顶层看到 50% 的蓝色 和 50% 的透明。通过透明部分,你可以看到底层有 50% 的红色(所以我们总共只看到 25% 的红色)。第二种情况的逻辑相同(50% 的红色 和 25% 的蓝色);因此你会看到不同的颜色,因为对于这两种情况,我们没有相同的比例。
为避免这种情况,您需要为两种颜色设置相同的比例。
这里有一个例子可以更好地说明和展示我们如何获得相同的颜色:
在顶层(内层)我们有 0.25
的不透明度(所以我们有 25% 的第一种颜色和 75% 的透明)然后对于底层(外层)我们具有 0.333
不透明度(所以我们有 75% 的 1/3 = 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% 以下:
.a {
background-color: rgba(255, 0, 0, 1) /*taking 40% even with opacity:1*/
}
.b {
background-color: rgba(0, 0, 255, 1) /*taking 40% even with opacity:1*/
}
.a > .b {
background-color: rgba(0, 0, 255, 0.6) /* taking 60%*/
}
.b > .a {
background-color: rgba(255, 0, 0, 0.6) /* taking 60%*/
}
<span class="a"><span class="b"> Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>
常见的琐碎情况是当顶层有 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)
),因此切换图层也会切换这些比例;因此我们看到了不同的 final 颜色。
现在,如果我们考虑第二个例子,我们将得到:
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
您可以使用 css 属性, mix-blend-mode : multiply
(limited browser support)
.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>
有关发生的情况的解释,请参阅 Temani Afif 的回答。
作为替代解决方案,您可以采用一个跨度,例如 a
,定位它并给它一个较低的 z-index,如果它在 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>
您正在按以下顺序混合三种颜色:
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))
你会得到不同的结果。这是因为使用 normal blend mode1,2 which is not commutative3 将前景颜色与背景颜色混合。而且由于它不可交换,交换前景色和背景色会产生不同的结果。
1 混合模式是一个函数,它接受前景和背景颜色,应用一些公式和 returns 结果颜色。
2 给定两种颜色,背景和前景,普通混合模式只是 returns 前景色。
3 如果更改操作数的顺序不会改变结果,则操作是可交换的,例如加法是可交换的 (1 + 2 = 2 + 1) 而减法不是 (1 - 2 ≠ 2 - 1)。
解决方案是使用可交换的混合模式:returns 同一颜色以任何顺序对同一对颜色使用相同的颜色(例如乘法混合模式,它将两种颜色相乘,returns 生成的颜色;或加深混合模式,returns 两者中较暗的颜色)。
$(function() {
$("#mode").on("change", function() {
var mode = $(this).val();
$("#demo").find(".a, .b").css({
"mix-blend-mode": mode
});
});
});
#demo > div {
width: 12em;
height: 5em;
margin: 1em 0;
}
#demo > div > div {
width: 12em;
height: 4em;
position: relative;
top: .5em;
left: 4em;
}
.a {
background-color: rgba(255, 0, 0, 0.5);
}
.b {
background-color: rgba(0, 0, 255, 0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="mode">
<optgroup label="commutative">
<option>multiply</option>
<option>screen</option>
<option>darken</option>
<option>lighten</option>
<option>difference</option>
<option>exclusion</option>
</optgroup>
<optgroup label="non-commutative">
<option selected>normal</option>
<option>overlay</option>
<option>color-dodge</option>
<option>color-burn</option>
<option>hard-light</option>
<option>soft-light</option>
<option>hue</option>
<option>saturation</option>
<option>color</option>
<option>luminosity</option>
</optgroup>
</select>
<div id="demo">
<div class="a">
<div class="b"></div>
</div>
<div class="b">
<div class="a"></div>
</div>
</div>
为了完整起见,这里是计算合成颜色的公式:
α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: 混合函数
为什么两个堆叠的半透明盒子的最终颜色取决于顺序?
我怎样才能在两种情况下得到相同的颜色?
.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>
仅仅是因为在这两种情况下,由于 top 层的不透明度如何影响 bottom[=99] 的颜色,颜色组合并不相同=]层.
对于第一种情况,您会在顶层看到 50% 的蓝色 和 50% 的透明。通过透明部分,你可以看到底层有 50% 的红色(所以我们总共只看到 25% 的红色)。第二种情况的逻辑相同(50% 的红色 和 25% 的蓝色);因此你会看到不同的颜色,因为对于这两种情况,我们没有相同的比例。
为避免这种情况,您需要为两种颜色设置相同的比例。
这里有一个例子可以更好地说明和展示我们如何获得相同的颜色:
在顶层(内层)我们有 0.25
的不透明度(所以我们有 25% 的第一种颜色和 75% 的透明)然后对于底层(外层)我们具有 0.333
不透明度(所以我们有 75% 的 1/3 = 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% 以下:
.a {
background-color: rgba(255, 0, 0, 1) /*taking 40% even with opacity:1*/
}
.b {
background-color: rgba(0, 0, 255, 1) /*taking 40% even with opacity:1*/
}
.a > .b {
background-color: rgba(0, 0, 255, 0.6) /* taking 60%*/
}
.b > .a {
background-color: rgba(255, 0, 0, 0.6) /* taking 60%*/
}
<span class="a"><span class="b"> Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>
常见的琐碎情况是当顶层有 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)
),因此切换图层也会切换这些比例;因此我们看到了不同的 final 颜色。
现在,如果我们考虑第二个例子,我们将得到:
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
您可以使用 css 属性, mix-blend-mode : multiply
(limited browser support)
.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>
有关发生的情况的解释,请参阅 Temani Afif 的回答。
作为替代解决方案,您可以采用一个跨度,例如 a
,定位它并给它一个较低的 z-index,如果它在 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>
您正在按以下顺序混合三种颜色:
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))
你会得到不同的结果。这是因为使用 normal blend mode1,2 which is not commutative3 将前景颜色与背景颜色混合。而且由于它不可交换,交换前景色和背景色会产生不同的结果。
1 混合模式是一个函数,它接受前景和背景颜色,应用一些公式和 returns 结果颜色。
2 给定两种颜色,背景和前景,普通混合模式只是 returns 前景色。
3 如果更改操作数的顺序不会改变结果,则操作是可交换的,例如加法是可交换的 (1 + 2 = 2 + 1) 而减法不是 (1 - 2 ≠ 2 - 1)。
解决方案是使用可交换的混合模式:returns 同一颜色以任何顺序对同一对颜色使用相同的颜色(例如乘法混合模式,它将两种颜色相乘,returns 生成的颜色;或加深混合模式,returns 两者中较暗的颜色)。
$(function() {
$("#mode").on("change", function() {
var mode = $(this).val();
$("#demo").find(".a, .b").css({
"mix-blend-mode": mode
});
});
});
#demo > div {
width: 12em;
height: 5em;
margin: 1em 0;
}
#demo > div > div {
width: 12em;
height: 4em;
position: relative;
top: .5em;
left: 4em;
}
.a {
background-color: rgba(255, 0, 0, 0.5);
}
.b {
background-color: rgba(0, 0, 255, 0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="mode">
<optgroup label="commutative">
<option>multiply</option>
<option>screen</option>
<option>darken</option>
<option>lighten</option>
<option>difference</option>
<option>exclusion</option>
</optgroup>
<optgroup label="non-commutative">
<option selected>normal</option>
<option>overlay</option>
<option>color-dodge</option>
<option>color-burn</option>
<option>hard-light</option>
<option>soft-light</option>
<option>hue</option>
<option>saturation</option>
<option>color</option>
<option>luminosity</option>
</optgroup>
</select>
<div id="demo">
<div class="a">
<div class="b"></div>
</div>
<div class="b">
<div class="a"></div>
</div>
</div>
为了完整起见,这里是计算合成颜色的公式:
α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: 混合函数