Abenteuer im CSS-Halbtransparent-Land

Avatar of Ana Tudor
Ana Tudor am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

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

Diagram. Illustrates how a bunch of semitransparent layers of various alphas are reduced to a single one. We start by taking the first two from the bottom and computing their equivalent, then we take this result and the third layer from the bottom and combine them into a single layer and so on.
Mehrere halbtransparente Ebenen auf eine einzige reduzieren.

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.

Screenshot collage.
Erwartetes Ergebnis mit identischen Panels links vs. dem leicht unterschiedlichen Ergebnis, das wir manchmal zwischen dem Zwei-Ebenen-Szenario (oben rechts) und dem Ein-Ebenen-Szenario (unten rechts) erhalten.

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.