Die Farbe der gestapelten halbtransparenten Kartons hängt von der Reihenfolge ab.

82

Warum hängt die endgültige Farbe von zwei gestapelten halbtransparenten Kartons von der Reihenfolge 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>

rmv
quelle
7
Ich kenne die Antwort auf die Frage nicht, aber das gleiche passiert in Photoshop und es ist etwas, das ich seit Jahren als Teil der Computerfarbtheorie akzeptiert habe. Ich werde mich umschauen, um zu sehen, ob ich weitere Informationen finden kann.
YAHsaves
11
Für das, 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 fällt auf Ihr Auge, sodass die Farbe einen größeren Einfluss auf die endgültige Farbe hat, selbst wenn beide eine Transparenz von 50% aufweisen.
jpa
4
@YAHsaves: Der Durchschnitt von 0 und 100 beträgt 50 (Schritt 1). Der Durchschnitt von 50 und 150 beträgt 100 (Schritt 2). Vergleichen Sie dies mit: Der Durchschnitt von 150 und 0 beträgt 75 (Schritt 1). Der Durchschnitt von 75 und 100 beträgt 87,5 (Schritt 2). Das Problem ist, dass die drei Zahlen nicht richtig gewichtet werden. Ein Durchschnitt muss basierend auf allen Zahlen gleichzeitig berechnet werden. Sie können den Durchschnitt nicht einfach Schritt für Schritt rekursiv berechnen. (Beachten Sie, dass die durchschnittliche Berechnung im Wesentlichen eine 50% ige Transparenzberechnung ist. Die Berechnung ändert sich für verschiedene Transparenzstufen, aber das Prinzip bleibt gleich.)
Flater
2
Lektionen gelernt: Mit 'Mix-Blend-Modus: Multiplizieren' erhalte ich eine Farbe unabhängig von der Stapelreihenfolge - das war es, wonach ich ursprünglich gesucht habe! Ich denke, die Antwort von @Moffens ist für jeden anderen Benutzer am nützlichsten, der mit dem gleichen Problem konfrontiert ist. Aber die Erklärungen von Temani Afif gelten tatsächlich für meine Frage und beschreiben, warum sich HTML anders verhält (es ahmt die Ausbreitung des physischen Lichts durch halbtransparente Folien nach), also geht das grüne Häkchen an ihn.
rmv

Antworten:

98

Einfach, weil in beiden Fällen die Farbkombination nicht gleich ist, da sich die Deckkraft der oberen Schicht auf die Farbe der unteren Schicht auswirkt .

Im ersten Fall sehen Sie 50% Blau und 50% Transparenz in der obersten Schicht. Durch den transparenten Teil sehen Sie 50% der roten Farbe in der unteren Schicht (also sehen wir insgesamt nur 25% der roten Farbe ). Gleiche Logik für den zweiten Fall ( 50% Rot und 25% Blau ); Daher sehen Sie unterschiedliche Farben, da wir in beiden Fällen nicht den gleichen Anteil 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 oberen Schicht (der inneren Spanne) haben wir eine 0.25Deckkraft (also haben wir 25% der ersten Farbe und 75% der Transparenz), und in der unteren Schicht (der äußeren Spanne) haben wir eine 0.333Deckkraft (also haben wir 1/3 von 75% = 25% der Farbe und der Rest ist transparent). Wir haben in beiden Schichten den gleichen Anteil (25%), sodass wir die gleiche Farbe sehen, auch wenn wir die Reihenfolge der Schichten 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>

Nebenbei bemerkt beeinflusst der weiße Hintergrund auch die Wiedergabe der Farben. 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 beide Farben den gleichen Anteil zu erzielen, wenn die Deckkraft der Deckschicht größer ist als 0.5die erste, da die erste mehr als 50% und die zweite weniger als 50% beträgt einer:

Der übliche triviale Fall ist, wenn die oberste Schicht opacity:1die oberste Farbe mit einem Anteil von 100% ergibt ; Somit ist es eine undurchsichtige Farbe.


Für eine genauere und präzisere Erklärung hier ist die Formel verwendet , um die Farbe , die wir nach der Kombination beiden Schichten sehen zu berechnen ref :

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

ColorF ist unsere endgültige Farbe. ColorT / ColorB sind die oberen und unteren Farben. opacityT / opacityB sind die oberen und unteren Opazitäten, die für jede Farbe definiert sind:

Das factorwird durch diese Formel definiert OpacityT + OpacityB*(1 - OpacityT).

Es ist klar, dass sich die beiden Ebenen factornicht ändern (sie bleiben konstant), aber wir können deutlich sehen, dass sich das Verhältnis für jede Farbe ändert, da wir nicht den gleichen Multiplikator haben.

Für unseren ersten Fall sind beide Trübungen 0.5so, dass wir haben werden:

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

Wie oben erläutert, hat die obere Farbe einen Anteil von 50% ( 0.5) und die untere Farbe einen Anteil von 25% ( 0.5*(1-0.5)), so dass durch das Wechseln der Schichten auch diese Anteile gewechselt werden. somit sehen wir eine andere endgültige Farbe.

Wenn wir nun das zweite Beispiel betrachten, haben wir:

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

In diesem Fall hat 0.25 = 0.333*(1 - 0.25)das Umschalten der beiden Ebenen keine Auswirkung. somit bleibt die Farbe gleich.

Wir können auch die trivialen Fälle klar identifizieren:

  • Wenn die oberste Schicht opacity:0die Formel hat, ist sie gleichColorF = ColorB
  • Wenn die oberste Schicht opacity:1die Formel hat, ist sie gleichColorF = ColorT
Temani Afif
quelle
23
@ ChrisHappy löse das Problem nicht;) erkläre .. die Erklärung ist manchmal besser als die Lösung
Temani Afif
Das Problem tritt auch dann noch auf, wenn Sie die Divs auseinander herausnehmen und positionieren: Absolut sie zu stapeln.
YAHsaves
1
@YAHsaves das Problem wird auch dann auftreten, wenn wir mehrere Hintergründe oder etwas verwenden, das die beiden Farben übereinander macht (mit absoluter Position oder nicht);)
Temani Afif
5
Wenn Sie eine TLDR hinzufügen möchten, sind diese multiplikativ statt additiv.
Caramiriel
2
@Caramiriel: "multiplikativ" würde immer noch nicht erklären, warum die Operation nicht kommutativ ist.
Eric Duminil
41

Sie können die CSS-Eigenschaft verwenden mix-blend-mode : multiply (eingeschränkte 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>

Moffen
quelle
6
Nahezu jeder Farbmischmodus aus dieser Liste, der "kommutativ" ist, reicht aus.
Salman A
Interessanterweise funktioniert dies mit Chrome, jedoch nicht mit Edge (ab dem neuesten Windows 10-Update).
Hong Ooi
3
@rmv warum würdest du etwas anderes als Overlay / Normal erwarten? Was ist die erwartete Farbe, wenn Sie eine undurchsichtige blaue Box vor einer roten Box positionieren ? Es wird blau statt rot oder die Funktion blau & rot sein.
Salman A
1
@Moffen Perfekte Antwort, aber können Sie bitte eine Erklärung hinzufügen, warum dies funktioniert und warum der ursprüngliche Code dies nicht tat?
Bergi
1
@rmv: Was der "normale" Mischmodus am ehesten imitiert, ist das Mischen von Farbe. Wenn Sie beispielsweise etwas weiße Farbe nehmen, die Hälfte durch rote Farbe und dann die Hälfte der resultierenden rosa Farbe durch blaue Farbe ersetzen, erhalten Sie ein bläuliches Lila (25% Weiß, 25% Rot, 50%). Blau). Wenn Sie mit derselben weißen Farbe beginnen, aber zuerst die Hälfte durch Blau und dann die Hälfte des Ergebnisses durch Rot ersetzen, erhalten Sie stattdessen ein rötliches Lila (25% Weiß, 25% Blau, 50% Rot).
Ilmari Karonen
22

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 im normalen Mischmodus 1,2 gemischt wird, der nicht kommutativ ist 3 . Und da es nicht kommutativ ist, führt das Vertauschen der Vorder- und Hintergrundfarben zu unterschiedlichen Ergebnissen.

1 Der Mischmodus ist eine Funktion, die eine Vordergrund- 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. B. den Multiplikations-Mischmodus, bei dem beide Farben multipliziert werden und die resultierende Farbe zurückgegeben wird, oder den dunklen Mischmodus, der zurückgibt die dunklere Farbe der beiden).


Der Vollständigkeit halber ist 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 Alpha-Wert der Vordergrundfarbe
Cb: der Farbwert der Hintergrundfarbe
αb: der Alpha-Wert der Hintergrundfarbe
B: die Mischfunktion

Salman A.
quelle
8

Eine Erklärung dessen, was passiert, finden Sie in der Antwort von Temani Afif.
Als alternative Lösung können Sie beispielsweise eine Spanne nehmen a, sie positionieren und einen niedrigeren Z-Index angeben, wenn sie sich im Inneren befindet b. Dann ist die Stapelung immer dieselbe: bwird ain der ersten Zeile oben und in der zweiten adarunter unten gezeichnet 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>

Herr Lister
quelle