我该怎样才能使两种情况下得到相同的颜色?
.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>
.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>
由于上层的透明度会影响底层颜色,因此在两种情况下颜色的组合不同。
对于第一种情况,您可以看到顶层有50%蓝色和50%透明度。透明部分显示了底层50%红色(因此总共只能看到25%红色)。对于第二种情况,同样的逻辑适用(50%红色和25%蓝色);因此,您将看到不同的颜色,因为对于两种情况,我们没有相同的比例。
要避免这种情况,您需要为两个颜色使用相同的比例。
以下是一个示例,以更好地说明和展示如何获得相同的颜色:
在顶层(内部span)中,我们有透明度0.25
(因此我们有第一种颜色的25%和75%的透明度),然后对于底层(外部span),我们有透明度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)
),因此切换图层也会切换这些比例;因此,我们看到了不同的最终颜色。
现在,如果我们考虑第二个示例,我们将有:
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
OpacityB=1.0
)和给定 OpacityT
的新透明颜色:
ColorT=-(((ColorF-ColorB)*OpacityB-ColorF)*OpacityT+(ColorB-ColorF)*OpacityB)/opacityT
这导致:
ColorT=(ColorB*OpacityT+ColorF-ColorB)/opacityT
- DrMarbuse您可以使用 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>
你正在按以下顺序混合三种颜色:
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))
但你得到了不同的结果。这是因为前景颜色与背景颜色使用正常混合模式1,2进行混合,而这种混合模式不具有交换律3。由于它不具备交换律,交换前景和背景颜色将产生不同的结果。
1 混合模式是一个接受前景色和背景色的函数,应用某些公式并返回结果颜色。
2 给定两种颜色,背景和前景,正常混合模式简单地返回前景色。
3 如果改变操作数的顺序不改变结果,则该运算是交换律的,例如加法是交换律的(1 + 2 = 2 + 1),而减法不是(1-2≠2-1)。
解决方案是使用具有交换律的混合模式:对于任何顺序相同的颜色对返回相同的颜色(例如乘法混合模式将两种颜色相乘并返回结果颜色;或者暗混合模式将返回两种颜色中更暗的颜色)。
$(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:混合函数
要了解发生的情况,请查看Temani Afif的回答。
作为另一种解决方案,您可以使用一个标签,例如a
,将其定位并在其内部降低z-index。然后堆叠顺序始终相同:第一行中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>