2つの積み重ねられた半透明のボックスの最終的な色が順序に依存するのはなぜですか?
どちらの場合でも同じ色になるようにするにはどうすればよいですか?
.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レイヤーの色にどのように影響するかにより、色の組み合わせが同じではないからです。
最初のケースでは、最上層に50%の青と50%の透明が表示されます。透明部分を通して、最下層に赤色の50%が表示されます(したがって、合計で25%の赤色のみが表示されます)。 2番目の場合と同じロジック(50%of red and 25%of blue);そのため、両方のケースで同じ割合がないため、異なる色が表示されます。
これを回避するには、両方の色で同じ比率にする必要があります。
同じ色をどのように得ることができるかをよりよく示し、示すための例を次に示します。
上のレイヤー(内側のスパン)には0.25
の不透明度があり(したがって最初の色の25%と75%の透明度があります)、そして下のレイヤー(外側のスパン)には0.333
の不透明度があります(したがって1/75%の3 =色の25%で、残りは透明です)。両方のレイヤーに同じ割合(25%)があるため、レイヤーの順序を逆にしてもsame colorが表示されます。
.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%以上であり、両方の色に同じ比率を持たせることはできないことに気付くかもしれません。 2番目のものは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%の割合でトップカラーを作成している場合です。したがって、これはopaqueの色です。
ここでのより正確で正確な説明については、両方のレイヤーの組み合わせ後に表示される色を計算するために使用される式ですref:
ColorF = (ColorT*opacityT + ColorB*OpacityB*(1 - OpacityT)) / factor
ColorFは最終色です。 ColorT/ColorBはそれぞれ上部と下部の色です。 opacityT/opacityBは、それぞれ各色に定義された上部および下部の不透明度です。
factor
は、この式OpacityT + OpacityB*(1 - OpacityT)
によって定義されます。
2つのレイヤーを切り替えてもfactor
は変わらないことは明らかです(定数のままです)が、同じ乗数がないため、各色の比率が変わることがはっきりとわかります。
最初のケースでは、両方の不透明度が0.5
であるため、次のようになります。
ColorF = (ColorT*0.5 + ColorB*0.5*(1 - 0.5)) / factor
上で説明したように、上の色の割合は50%(0.5
)で、下の色の割合は25%(0.5*(1-0.5)
)なので、レイヤーを切り替えるとこれらの割合も切り替わります。したがって、異なるfinal色が表示されます。
2番目の例を考慮すると、次のようになります。
ColorF = (ColorT*0.25 + ColorB*0.333*(1 - 0.25)) / factor
この場合、0.25 = 0.333*(1 - 0.25)
があるため、2つのレイヤーを切り替えても効果はありません。したがって、色は変わりません。
些細なケースも明確に特定できます。
opacity:0
がある場合、式はColorF = ColorB
と等しくなりますopacity:1
がある場合、式はColorF = ColorT
と等しくなります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>
次の順序で3色を混合しています。
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 commutative ではありません。そして、それは交換可能ではないので、前景色と背景色を交換すると異なる結果が生じます。
1 ブレンドモードは、前景色と背景色を受け入れ、数式を適用して、結果の色を返す関数です。
解決策は、交換可能なブレンディングモードを使用することです:同じ色のペアに対して同じ色を任意の順序で返すモード(たとえば、両方の色を乗算して結果の色を返す乗算ブレンドモード、または2つの暗い色)。
$(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:前景色のアルファ値
Cb:背景色の色の値
αb:背景色のアルファ値B:ブレンド関数
何が起こるかの説明については、Temani Afifの回答を参照してください。
代替ソリューションとして、a
などの1つのスパンを配置し、それを配置し、b
内にある場合は、より低いzインデックスを指定できます。スタックは常に同じになります。最初の行のb
の上にa
が描かれ、2番目の行の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>