Warum hängt die endgültige Farbe von zwei gestapelten halbtransparenten Boxen von der Bestellung ab?
Wie könnte ich es schaffen, dass ich in beiden Fällen die gleiche Farbe bekomme?
.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>
Einfach weil in beiden Fällen die Farbkombination aufgrund der Deckkraft nicht gleich ist oben Schicht beeinflussen die Farbe der Unterseite Schicht.
Für den ersten Fall sehen Sie 50% blau und 50 % transparent in der obersten Schicht. Durch den transparenten Teil sehen Sie 50 % der roten Farbe in der unteren Schicht (also sehen wir nur 25 % rot in Summe). Gleiche Logik für den zweiten Fall (50 % rot und 25 % blau); Sie werden also unterschiedliche Farben sehen, da wir in beiden Fällen nicht die gleichen Proportionen haben.
Um dies zu vermeiden, müssen Sie für beide Farben den gleichen Anteil haben.
Hier ist ein Beispiel, um besser zu veranschaulichen und zu zeigen, wie wir dieselbe Farbe erhalten können:
In der obersten Schicht (der inneren Spannweite) haben wir 0.25
Deckkraft (also haben wir 25 % der ersten Farbe und 75 % transparent) dann für die untere Schicht (die äußere Spanne) haben wir 0.333
Deckkraft (also haben wir 1/3 von 75 % = 25 % der Farbe und der Rest ist transparent). Wir haben den gleichen Anteil in beiden Schichten (25%), also sehen wir das selbe Farbe auch wenn wir die Reihenfolge der Ebenen umkehren.
.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>
Als Nebenbemerkung wirkt sich der weiße Hintergrund auch auf die Wiedergabe der Farben aus. Sein Anteil beträgt 50 %, was das logische Ergebnis von 100 % ergibt (25 % + 25 % + 50 %).
Möglicherweise stellen Sie auch fest, dass es nicht möglich ist, für unsere beiden Farben die gleichen Proportionen zu haben, wenn die Deckkraft der obersten Ebene größer als ist 0.5
weil der der erste hat mehr als 50% und es bleibt weniger als 50% für die zweite:
.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>
Der übliche triviale Fall ist, wenn die oberste Schicht hat opacity:1
die die Deckfarbe mit einem Anteil von 100% ausmachen; also ist es ein undurchsichtig Farbe.
Für eine genauere und präzisere Erklärung ist hier die Formel, die verwendet wird, um die Farbe zu berechnen, die wir nach der Kombination beider Schichten sehenRef:
ColorF = (ColorT*opacityT + ColorB*OpacityB*(1 - OpacityT)) / factor
FarbeF ist unsere letzte Farbe. FarbeT/FarbeB sind jeweils die oberen und unteren Farben. OpazitätT/OpazitätB sind jeweils die oberen und unteren Opazitäten, die für jede Farbe definiert sind:
Der factor
ist durch diese Formel definiert OpacityT + OpacityB*(1 - OpacityT)
.
Es ist klar, dass, wenn wir die beiden Schichten tauschen factor
wird sich nicht ändern (es wird eine Konstante bleiben), aber wir können deutlich sehen, dass sich der Anteil für jede Farbe ändern wird, da wir nicht denselben Multiplikator haben.
Für unseren Ausgangsfall sind beide Opazitäten 0.5
also werden wir haben:
ColorF = (ColorT*0.5 + ColorB*0.5*(1 - 0.5)) / factor
Wie oben erklärt, hat die oberste Farbe einen Anteil von 50% (0.5
) und der unterste hat einen Anteil von 25 % (0.5*(1-0.5)
), sodass beim Wechseln der Ebenen auch diese Proportionen geändert werden; so sehen wir ein anderes Finale Farbe.
Wenn wir nun das zweite Beispiel betrachten, erhalten wir:
ColorF = (ColorT*0.25 + ColorB*0.333*(1 - 0.25)) / factor
In diesem Fall haben wir 0.25 = 0.333*(1 - 0.25)
Das Wechseln der beiden Ebenen hat also keine Auswirkung. somit bleibt die farbe gleich.
Wir können auch die trivialen Fälle klar identifizieren:
- Wenn die oberste Schicht hat
opacity:0
Die Formel ist gleich ColorF = ColorB
- Wenn die oberste Schicht hat
opacity:1
Die Formel ist gleich ColorF = ColorT
Sie können die CSS-Eigenschaft verwenden, mix-blend-mode : multiply
(begrenzt Browserunterstützung)
.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>
Sie mischen drei Farben in der folgenden Reihenfolge:
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))
Und Sie erhalten unterschiedliche Ergebnisse. Dies liegt daran, dass die Vordergrundfarbe mit der Hintergrundfarbe gemischt wird normaler Mischmodus1,2 was nicht ist kommutativ3. Und da es nicht kommutativ ist, führt das Vertauschen von Vorder- und Hintergrundfarbe zu unterschiedlichen Ergebnissen.
1 Der Mischmodus ist eine Funktion, die eine Vorder- und Hintergrundfarbe akzeptiert, eine Formel anwendet und die resultierende Farbe zurückgibt.
2 Bei zwei Farben, Hintergrund und Vordergrund, gibt der normale Mischmodus einfach die Vordergrundfarbe zurück.
3 Eine Operation ist kommutativ, wenn eine Änderung der Reihenfolge der Operanden das Ergebnis nicht ändert, z. B. ist die Addition kommutativ (1 + 2 = 2 + 1) und die Subtraktion nicht (1 – 2 ≠ 2 – 1).
Die Lösung besteht darin, einen kommutativen Mischmodus zu verwenden: einen, der dieselbe Farbe für dasselbe Farbpaar in beliebiger Reihenfolge zurückgibt (z die dunklere Farbe der beiden).
$(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>
Der Vollständigkeit halber hier die Formel zur Berechnung der zusammengesetzten Farbe:
αs x (1 - αb) x Cs + αs x αb x B(Cb, Cs) + (1 - αs) x αb x Cb
mit:
Cs: der Farbwert der Vordergrundfarbe
αs: der Alphawert der Vordergrundfarbe
Cb: der Farbwert der Hintergrundfarbe
αb: der Alpha-Wert der Hintergrundfarbe
B: die Mischfunktion
Eine Erklärung dessen, was passiert, finden Sie in der Antwort von Temani Afif.
Als alternative Lösung können Sie eine Span nehmen, a
Positionieren Sie es beispielsweise und geben Sie ihm einen niedrigeren Z-Index, wenn es sich darin befindet b
. Dann ist die Stapelung immer gleich: b
darüber gezogen wird a
in der ersten Zeile und a
darunter gezogen wird b
in dieser Sekunde.
.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>
.
Ich kenne die Antwort auf die Frage nicht, aber das Gleiche passiert in Photoshop, und es ist etwas, das ich seit Jahren nur als Teil der Computer-Farbtheorie akzeptiere. Ich werde mich umsehen, ob ich weitere Informationen finden kann.
– YAHsaves
28. Mai 18 um 23:41 Uhr
Für was es wert ist, passiert dasselbe im wirklichen Leben für alles, was nicht 100% transparent ist und von vorne beleuchtet wird. Mehr Licht vom vorderen Objekt trifft auf Ihr Auge, daher hat seine Farbe einen größeren Einfluss auf die endgültige Farbe, selbst wenn beide 50 % Transparenz aufweisen.
– jpa
29. Mai 18 um 5:27 Uhr
@YAHsaves: Der Durchschnitt von 0 und 100 ist 50 (Schritt 1). Der Durchschnitt von 50 und 150 ist 100 (Schritt 2). Vergleichen Sie dies mit: Der Durchschnitt von 150 und 0 ist 75 (Schritt 1). Der Durchschnitt von 75 und 100 ist 87,5 (Schritt 2). Das Problem ist, dass die drei Zahlen nicht richtig gewichtet werden. Aus allen Zahlen gleichzeitig muss ein Durchschnitt berechnet werden; Sie können den Durchschnitt nicht einfach Schritt für Schritt rekursiv berechnen. (Beachten Sie, dass die Durchschnittsberechnung im Wesentlichen eine 50%-Transparenzberechnung ist. Die Berechnung ändert sich für verschiedene Transparenzstufen, aber das Prinzip bleibt gleich.)
– Flacher
29. Mai 18 um 10:51 Uhr
Gelernte Lektionen: Mit ‘mix-blend-mode: multiply’ erhalte ich eine Farbe, die unabhängig von der Stapelreihenfolge ist – danach habe ich ursprünglich gesucht! Ich denke, die Antwort von @Moffens ist für jeden anderen Benutzer am nützlichsten, der vor demselben Problem steht. Aber die Erklärungen von Temani Afif treffen tatsächlich auf meine Frage zu und beschreiben, warum sich HTML anders verhält (es imitiert die physikalische Lichtausbreitung durch halbtransparente Folien), also geht das grüne Häkchen an ihn.
– rmw
29. Mai ’18 um 17:38 Uhr