Kürzlich wurde ich gebeten, einige Anpassungen an einer Landingpage vorzunehmen, und unter den Dingen, die ich im Code fand, befanden sich zwei halbtransparente Überlagerungen – beide mit denselben RGB-Werten für die background-color – über einem Bild. So etwas
<img src='myImage.jpg'/>
<div class='over1'></div>
<div class='over2'></div>
Es gab keinen Zweck, zwei davon zu haben, außer dass nur einer das Bild nicht genug einfärbte. Aus irgendeinem Grund dachte derjenige, der die Seite ursprünglich programmiert hat, dass das Hinzufügen einer weiteren halbtransparenten Überlagerung eine bessere Idee war, als die opacity der ersten zu erhöhen.
Also beschloss ich, eine Ebene wegzulassen und der verbleibenden Ebene einen opacity-Wert zu geben, der ein visuell äquivalentes Ergebnis wie das ursprüngliche erzielen würde, das durch zwei Ebenen erzielt wurde. In Ordnung, aber wie erhalten wir die äquivalente opacity einer Ebene?
Wenn Sie sich an meinen Crashkurs in mask-Compositing erinnern, haben Sie vielleicht schon die Antwort erraten, denn es ist genau die gleiche Formel, die wir auch für die add-Compositing-Operation verwenden! Bei zwei Ebenen mit den Alphawerten a0 und a1 ist der resultierende Alpha-Wert
a0 + a1 - a0⋅a1
Die interaktive Demo unten zeigt einen vergleichenden Blick auf eine Zwei-Ebenen-Überlagerung mit den Alphawerten a0 und a1 (die Sie über die Bereichseingaben steuern können) im Vergleich zu einer Ein-Ebenen-Überlagerung mit einem Alpha-Wert von a0 + a1 - a0⋅a1.
Sehen Sie das Pen von thebabydino (@thebabydino) auf CodePen.
Komischerweise sehen sie identisch aus, wenn wir das Bild entfernen (über die Checkbox am unteren Rand der Demo), scheinen aber mit dem darunter liegenden Bild etwas anders auszusehen. Vielleicht ist der Unterschied nur meine Einbildung, da das Bild an manchen Stellen heller und an anderen dunkler ist.
Es sieht definitiv nicht anders aus, wenn wir sie nicht nebeneinander haben und einfach zwischen den beiden Ebenen mit den Alphawerten a0 und a1 und der einen Ebene mit dem Alpha-Wert a0 + a1 - a0⋅a1 wechseln.
Sehen Sie das Pen von thebabydino (@thebabydino) auf CodePen.
Dies kann auf mehrere Ebenen erweitert werden. In diesem Fall berechnen wir die äquivalente Ebene der beiden unteren Ebenen, dann die äquivalente Ebene dieses Ergebnisses und der darüber liegenden Ebene und so weiter

Das Spielen damit hat mich auch über das feste background-Äquivalent einer festen Ebene (c0) mit einer halbtransparenten Überlagerung (c1 mit einem Alpha von a) nachdenken lassen. In diesem Fall wird der background der Ein-Ebenen-Äquivalenz auf Kanalbasis berechnet, wobei die resultierenden Kanäle sind
ch0 + (ch1 - ch0)*a
…wobei ch0 ein Kanal (rot, grün oder blau) der festen unteren Ebene ist, ch1 der entsprechende Kanal der oberen halbtransparenten Ebene und a der Alpha-Wert derselben oberen halbtransparenten Ebene.
Wenn wir das in Sass-Code umsetzen, haben wir
/* per channel function */
@function res-ch($ch0, $ch1, $a) {
@return $ch0 + ($ch1 - $ch0)*$a
}
@function res-col($c0, $c1, $a) {
$ch: 'red' 'green' 'blue'; /* channel names */
$nc: length($ch); /* number of channels */
$ch-list: ();
@for $i from 0 to $nc {
$fn: nth($ch, $i + 1);
$ch-list: $ch-list,
res-ch(call($fn, $c0), call($fn, $c1), $a);
}
@return RGB($ch-list)
}
Die interaktive Demo unten (mit der wir die RGB-Werte der beiden Ebenen sowie das Alpha der oberen Ebene auswählen können, indem wir auf die Farbfelder bzw. den Alpha-Wert klicken) zeigt einen vergleichenden Blick auf die Zwei-Ebenen-Variante im Vergleich zu unserer berechneten Ein-Ebenen-Variante.
Sehen Sie das Pen von thebabydino (@thebabydino) auf CodePen.
Abhängig vom Gerät, Betriebssystem und Browser können Sie feststellen, dass die beiden Panels in der obigen Demo identische Hintergründe haben… oder nicht. Die Formel ist korrekt, aber wie unterschiedliche Browser auf unterschiedlichen Betriebssystemen und Geräten mit dem Zwei-Ebenen-Fall umgehen, kann variieren.

Ich habe auf Twitter nach Screenshots eines vereinfachten Testfalls gefragt, und aus den Antworten, die ich erhielt, scheinen die beiden Panels auf mobilen Browsern immer gleich auszusehen, unabhängig davon, ob wir von Android- oder iOS-Geräten oder von Firefox auf einem beliebigen Betriebssystem sprechen. Sie scheinen auch fast immer unter Windows identisch zu sein, obwohl ich eine Antwort erhalten habe, die besagt, dass sowohl Chrome als auch Chromium Edge die beiden Panels manchmal unterschiedlich anzeigen können.
Bei WebKit-Browsern unter macOS und Linux sind die Ergebnisse sehr gemischt, wobei die Panels in den meisten Fällen leicht unterschiedlich sind. Das Wechseln zu einem sRGB-Profil kann sie jedoch identisch machen. Das Lustigste hierbei ist, dass beim Verwenden eines Zwei-Monitor-Setups das Ziehen des Fensters von einem Monitor zum anderen den Unterschied ausmachen kann, ob die beiden Panels erscheinen oder verschwinden.
In einem realen Anwendungsfall ist der Unterschied jedoch ziemlich gering und wir werden die beiden Panels niemals nebeneinander haben. Selbst wenn es einen Unterschied gibt, wird niemand davon erfahren, es sei denn, er testet die Seite unter verschiedenen Szenarien, was wahrscheinlich nur ein Webentwickler tun würde. Und es ist nicht so, dass wir keine Unterschiede zwischen der Darstellung derselben einfachen Volltonhintergründe auf verschiedenen Geräten, Betriebssystemen und Browsern hätten. Zum Beispiel sieht #ffa800, das hier auf CSS-Tricks oft verwendet wird, auf meinen Ubuntu- und Windows-Laptops nicht gleich aus. Dasselbe gilt für die Art und Weise, wie Menschen Dinge unterschiedlich wahrnehmen können.
Interessant. Ich habe kürzlich ähnliche Beobachtungen gemacht. Ich musste eine bestehende Animation neu erstellen, bei der ich die ursprünglichen Farben und Opazitätswerte nicht kannte. Um sie zu erhalten, nahm ich einige Pixelwerte, setzte sie in die Mischformeln ein und erstellte ein System linearer Gleichungen, das ich nach RGB-Werten und Opazitäten löste.
Da die Animation in 3D war, machte ich dasselbe für einige der verwendeten Koordinaten, um Dimensionen sowie Transformations- und Projektionsmatrizen zu bestimmen. Spaßige Sache.
Eine Sache, die man beim Mischen beachten sollte, ist die Gammakorrektur. Ich bin mir nicht sicher, wie Webstandards oder Browser dies handhaben, aber unterschiedliche Handhabungen könnten auch zu sehr sichtbaren Unterschieden führen
https://en.wikipedia.org/wiki/Alpha_compositing#Composing_alpha_blending_with_gamma_correction
In einem verwandten Zusammenhang haben Verläufe auch Probleme mit Gamma und Interpolation in RGB. Sie würden oft viel besser aussehen, wenn sie mit korrekter Interpolation erstellt würden, da dies ein viel sanfterer Übergang ist. Überprüfen Sie hier den Abschnitt "Gradients", wenn Sie interessiert sind: https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/
Es gibt auch eine nette Diskussion hier: https://github.com/w3c/csswg-drafts/issues/4647
Aber ich schweife ab… Danke für deinen Artikel!