Bis 2020 waren Mischmodi eine Funktion, die ich nicht viel benutzt hatte, weil ich selten eine Ahnung hatte, welches Ergebnis sie produzieren konnten, ohne sie zuerst auszuprobieren. Und den Ansatz „Probieren Sie es aus und sehen Sie, was passiert“, schien mich immer entsetzt über das visuelle Erbrochene, das ich geschafft hatte, auf dem Bildschirm zu erstellen.
Das Problem beruhte darauf, nicht wirklich zu wissen, wie sie im Rücken arbeiten. So ziemlich jeder Artikel, den ich zu diesem Thema gesehen habe, basiert auf Beispielen, Vergleiche mit Photoshop oder ausführlichen künstlerischen Beschreibungen. Ich finde Beispiele großartig, aber wenn Sie keine Ahnung haben, wie die Dinge im Rücken funktionieren, wird eine gut aussehende Demo in etwas anpasst, das eine andere Idee, die Sie in Ihrem Kopf haben, zu einem wirklich zeitaufwändigen, frustrierenden und letztendlich vergeblichen Abenteuer werden. Dann sind Photoshop -Vergleiche für jemanden, der aus technischem Hintergrund kommt, ziemlich nutzlos. Und ausführliche künstlerische Beschreibungen fühlen sich für mich wie eine Pinguinsprache an.
Ich hatte also einen Moment der Glühbirne, als ich auf die Spezifikation stieß und feststellte, dass sie auch mathematische Formeln enthält, nach denen die Mischmodi funktionieren. Dies bedeutete, dass ich endlich verstehen konnte, wie dieses Zeug im Rücken funktioniert und wo es wirklich nützlich sein kann. Und jetzt, wo ich es besser weiß, werde ich dieses Wissen in einer Reihe von Artikeln teilen.
Heute werden wir uns darauf konzentrieren, wie das Mischen im Allgemeinen funktioniert, dann zwei ähnliche Mischmodi - Unterschied und Ausschluss - genauer betrachten und schließlich zu dem Fleisch dieses Artikels gelangen, in dem wir einige coole Anwendungsfälle wie die folgenden analysieren werden.
Mischungen bedeutet, zwei Schichten zu kombinieren (die übereinander gestapelt sind) und eine einzige Schicht zu bekommen. Diese beiden Schichten könnten zwei Geschwister sein. In diesem Fall ist die von uns verwendete CSS-Eigenschaft Mix-Blend-Mode. Sie könnten auch zwei Hintergrundschichten sein. In diesem Fall ist die von uns verwendete CSS-Eigenschaft im Hintergrund. Beachten Sie, dass bei der Spreche über das Mischen von „Geschwistern“ das Mischen eines Elements mit den Pseudo-Elementen oder mit dem Textinhalt oder dem Hintergrund seines übergeordneten übergeordnet ist. Und wenn es um Hintergrundschichten geht, sind es nicht nur die Hintergrundbildschichten, über die ich spreche-die Hintergrundfarbe ist auch eine Ebene.
Beim Mischen von zwei Schichten wird die Schicht oben als Quelle bezeichnet, während die darunter liegende Ebene das Ziel genannt wird. Das nehme ich einfach so, weil diese Namen zumindest für mich nicht viel Sinn machen. Ich würde erwarten, dass das Ziel eine Ausgabe ist, aber stattdessen sind sie beide Eingänge und die resultierende Schicht ist die Ausgabe.
Wie genau wir die beiden Schichten kombinieren, hängt vom jeweiligen Mischmodus ab, aber es ist immer pro Pixel. In der folgenden Abbildung wird beispielsweise der Multiply -Mischmodus verwendet, um die beiden Schichten zu kombinieren, die als Pixelgitter dargestellt werden.
Okay, aber was passiert, wenn wir mehr als zwei Schichten haben? Nun, in diesem Fall findet der Mischprozess in Phasen von unten statt.
In einer ersten Stufe ist die zweite Schicht von unten unsere Quelle und die erste Schicht von unten ist unser Ziel. Diese beiden Schichten mischen sich zusammen und das Ergebnis wird zum Ziel für die zweite Stufe, wo die dritte Schicht von unten die Quelle ist. Das Mischen der dritten Schicht mit dem Ergebnis des Mischens der ersten beiden gibt uns das Ziel für die dritte Stufe, wobei die vierte Schicht von unten die Quelle ist.
Natürlich können wir in jeder Phase einen anderen Mischmodus verwenden. Zum Beispiel können wir Differenz verwenden, um die ersten beiden Schichten von unten zu mischen und dann das Ergebnis mit der dritten Schicht von unten zu mischen. Aber das ist etwas, in das wir uns in zukünftigen Artikeln ein bisschen mehr einlassen werden.
Das Ergebnis der beiden hier diskutierten Mischmodi hängt nicht davon ab, welcher der beiden Schichten oben ist. Beachten Sie, dass dies bei allen möglichen Mischmodi nicht der Fall ist, aber für diejenigen, die wir in diesem Artikel betrachten.
Sie sind auch trennbare Mischmodi, dh der Mischvorgang wird separat an jedem Kanal durchgeführt. Dies ist auch bei allen möglichen Mischmodi nicht der Fall, aber es ist der Fall bei Differenz und Ausschluss.
Genauer, der resultierende rote Kanal hängt nur vom roten Kanal der Quelle und dem roten Kanal des Ziels ab. Der resultierende grüne Kanal hängt nur vom grünen Kanal der Quelle und dem grünen Kanal des Ziels ab. Und schließlich hängt der resultierende blaue Kanal nur vom blauen Kanal der Quelle und dem blauen Kanal des Ziels ab.
R = f <sub>b</sub> (r <sub>s</sub> , r <sub>d</sub> ) G = f <sub>b</sub> (g <sub>s</sub> , g <sub>d</sub> ) B = F <sub>B</sub> (B <sub>S</sub> , B <sub>D</sub> )
Für einen generischen Kanal, ohne festzulegen, ob es rot, grün oder blau ist, ist es eine Funktion der beiden entsprechenden Kanäle in der Quellschicht (obere) und in der Zielschicht (unten):
CH = F <sub>B</sub> (CH <sub>S</sub> , CH <sub>D</sub> )
Beachten Sie, dass RGB -Werte entweder im Intervall [0, 255] oder als Prozentsätze im Intervall [0%, 100%] dargestellt werden können, und was wir in unseren Formeln tatsächlich verwenden, ist der Prozentsatz, der als Dezimalwert ausgedrückt wird. Zum Beispiel kann Crimson entweder als RGB (220, 20, 60) oder als RGB (86,3%, 7,8%, 23,5%) geschrieben werden - beide sind gültig. Die Kanalwerte, die wir für Berechnungen verwenden, wenn ein Pixel purpurrot ist, sind die als Dezimalwerte ausgedrückten Prozentsätze, das sind 0,863, 0,078, .235.
Wenn ein Pixel schwarz ist, sind die Kanalwerte, die wir für Berechnungen verwenden, alle 0, da Schwarz als RGB (0, 0, 0) oder als RGB (0%, 0%, 0%) geschrieben werden kann. Wenn ein Pixel weiß ist, sind die Kanalwerte, die wir für Berechnungen verwenden, alle 1, da Weiß als RGB (255, 255, 255) oder als RGB (100%, 100%, 100%) geschrieben werden kann.
Beachten Sie, dass das Ergebnis mit der anderen Schicht identisch ist, wo immer wir die volle Transparenz haben (ein Alpha gleich 0).
Der Name dieses Mischmodus kann einen Hinweis darauf geben, wie die Mischfunktion F B () ausreicht. Das Ergebnis ist der absolute Wert der Differenz zwischen den entsprechenden Kanalwerten für die beiden Schichten.
CH = F <sub>B</sub> (CH <sub>S</sub> , CH <sub>D</sub> ) = | CH S - CH D |
Zuerst bedeutet dies, dass, wenn die entsprechenden Pixel in den beiden Schichten identische RGB -Werte haben (dh CH S = CH D für jeden der drei Kanäle), das Pixel der resultierenden Schicht schwarz ist, da die Unterschiede für alle drei Kanäle 0 sind.
Ch <sub>s</sub> = ch <sub>d</sub> CH = F <sub>B</sub> (CH <sub>S</sub> , CH <sub>D</sub> ) = | CH <sub>S</sub> - CH <sub>D</sub> | = 0
Zweitens, da der Absolutwert der Differenz zwischen einer positiven Zahl und 0 diese Zahl unverändert lässt, führt dies zu dem entsprechenden Ergebnispixel mit dem gleichen RGB -Wert wie das Pixel der anderen Schicht, wenn das Pixel einer Schicht schwarz ist (alle Kanäle sind gleich 0).
Wenn sich das schwarze Pixel in der oberen (Quell-) Ebene befindet, gibt uns die Kanalwerte durch 0 in unserer Formel aus:
CH = F <sub>B</sub> (0, CH <sub>D</sub> ) = | 0 - CH <sub>D</sub> | = | -Ch <sub>d</sub> | = Ch <sub>d</sub>
Wenn sich das schwarze Pixel in der unteren (Ziel-) Ebene befindet, gibt uns die Kanalwerte durch 0 in unserer Formel aus:
CH = F <sub>B</sub> (CH <sub>S</sub> , 0) = | CH <sub>S</sub> - 0 | = | Ch <sub>s</sub> | = Ch <sub>s</sub>
Da der Absolutwert der Differenz zwischen einer positiven Untereinzahlung und 1 die Komplement dieser Zahl ergibt, ergibt sich schließlich, dass das entsprechende Ergebnispixel, wenn das Pixel einer Schicht weiß ist (alle Kanäle 1), das Pixel der anderen Schicht vollständig invertiert ist (welcher Filter: Invert (1) würde es tun.
Wenn sich das weiße Pixel in der oberen (Quell-) Ebene befindet, gibt uns die Kanalwerte durch 1 in unserer Formel aus:
CH = F <sub>B</sub> (1, CH <sub>D</sub> ) = | 1 - CH <sub>D</sub> | = 1 - ch <sub>d</sub>
Wenn sich das weiße Pixel in der unteren (Ziel-) Ebene befindet, gibt uns die Kanalwerte durch 1 in unserer Formel aus:
CH = F <sub>B</sub> (CH <sub>S</sub> , 1) = | CH <sub>S</sub> - 1 | = 1 - ch <sub>s</sub>
Dies ist in der folgenden interaktiven Stift in Aktion zu sehen, wo Sie zwischen der Anzeige der getrennten Schichten und dem Betrachten überlappend und mischt werden können. Wenn Sie die drei Spalten im überlappenden Fall schweben, zeigt auch, was für jeden passiert.
Für den zweiten und letzten Mischmodus, den wir heute sehen, ist das Ergebnis doppelt so hoch wie die beiden Kanalwerte, die von ihrer Summe abgezogen werden:
CH = F <sub>B</sub> (CH <sub>S</sub> , CH <sub>D</sub> ) = CH S CH D - 2 · CH S · CH D D D.
Da sich beide Werte im Intervall [0, 1] befinden, ist ihr Produkt immer höchstens der kleinsten von ihnen, sodass das doppelt so hoch wie das Produkt immer höchstens ihrer Summe ist.
Wenn wir ein schwarzes Pixel in der oberen (Quell-) Ebene betrachten, ersetzen Sie CH S durch in der obigen Formel durch CH S durch, erhalten wir das folgende Ergebnis für die entsprechenden Kanäle des entsprechenden Pixel:
CH = F <sub>B</sub> (0, CH <sub>D</sub> ) = 0 CH <sub>D</sub> - 2 · 0 · CH <sub>D</sub> = CH <sub>D</sub> - 0 = CH <sub>D D.</sub>
Wenn wir ein schwarzes Pixel in der unteren (Ziel-) Ebene betrachten, ersetzen Sie CH D durch die obigen Formel durch 0, erhalten wir das folgende Ergebnis für die entsprechenden Kanäle des entsprechenden Ergebnispixels:
CH = F <sub>B</sub> (CH <sub>S</sub> , 0) = CH <sub>S</sub> 0 - 2 · CH <sub>S</sub> · 0 = CH <sub>S</sub> - 0 = CH <sub>S</sub>
Wenn also das Pixel einer Schicht schwarz ist, entsteht das entsprechende Ergebnispixel mit dem Pixel der anderen Schicht.
Wenn wir ein weißes Pixel in der oberen (Quell-) Ebene betrachten, ersetzen Sie CH S durch 1 in der obigen Formel, wir erhalten das folgende Ergebnis für die entsprechenden Kanäle des entsprechenden Ergebnispixels:
CH = F <sub>B</sub> (1, CH <sub>D</sub> ) = 1 CH <sub>D</sub> - 2 · 1 · CH <sub>D</sub> = 1 CH <sub>D</sub> - 2 · CH D = 1 - CH D D <sub>D</sub> = 1 CH D - 2 · CH D = 1 - <sub>CH D</sub>
Wenn wir ein weißes Pixel in der unteren (Ziel-) Ebene betrachten, ersetzen Sie CH D durch 1 in der obigen Formel, wir erhalten das folgende Ergebnis für die entsprechenden Kanäle des entsprechenden Ergebnispixels:
CH = F <sub>B</sub> (CH <sub>S</sub> , 1) = CH <sub>S</sub> 1 - 2 · CH <sub>S</sub> · 1 = CH <sub>S</sub> 1 - 2 · CH <sub>S</sub> = 1 - CH <sub>S</sub>
Wenn also das Pixel einer Schicht weiß ist, entsteht das entsprechende Ergebnispixel mit dem Pixel der anderen Schicht invertiert.
Dies ist alles in der folgenden interaktiven Demo gezeigt:
Beachten Sie, dass bis zu mindestens eine der Schichten nur Schwarz -Weiß -Pixel aufweist, Unterschied und Ausschluss genau das gleiche Ergebnis.
Hier kommt der interessante Teil - die Beispiele!
Nehmen wir an, wir haben einen Absatz mit einem Link:
<p> Hallo, <a href="'#'"> Welt </a>! </p>
Wir setzen zunächst ein paar grundlegende Stile ein, um unseren Text in die Mitte des Bildschirms zu stecken, seine Schriftgröße zu erhöhen, einen Hintergrund auf den Körper und eine Farbe sowohl auf dem Absatz als auch auf dem Link zu setzen.
Körper { Anzeige: Grid; Ort-in-intent: Zentrum; Höhe: 100VH; Hintergrund: #222; Farbe: #ddd; Schriftgröße: Clamp (1,25EM, 15VW, 7EM); } a {Farbe: Gold; }
Sieht bisher nicht nach viel nach, aber wir werden das bald ändern!
Der nächste Schritt besteht darin, eine absolut positionierte Pseudo-Elemente zu erstellen, die den gesamten Link abdeckt und seinen Hintergrund auf CurrentColor eingestellt hat.
A { Position: Relativ; Farbe: Gold; &::nach { Position: absolut; Top: 0; unten: 0; Rechts: 0; links: 0; Hintergrund: CurrentColor; Inhalt: ''; } }
Das Obige sieht so aus, als hätten wir Dinge durcheinander gebracht ... aber haben wir wirklich? Was wir hier haben, ist ein goldenes Rechteck über Goldtext. Und wenn Sie darauf geachtet haben, wie die beiden oben diskutierten Mischmodi gearbeitet haben, haben Sie wahrscheinlich bereits vermutet, was als nächstes kommt-wir mischen die beiden Geschwisterknoten in den Link (das Pseudo-Element-Rechteck und den Textinhalt) mit Differenz, und da sie beide Gold sind, entsteht es, dass das, was sie gemeinsam haben, schwarz wird.
P {Isolation: Isolat; } A { / * wie früher */ &::nach { / * wie früher */ Mix-Blend-Mode: Differenz; } }
Beachten Sie, dass wir den Absatz isolieren müssen, um das Mischen mit dem Körperhintergrund zu verhindern. Während dies nur ein Problem in Firefox ist (und da wir einen sehr dunklen Hintergrund am Körper haben, ist es nicht allzu auffällig) und in Chrom in Ordnung ist, denken Sie daran, dass das, was Firefox tut, laut der Spezifikation tatsächlich korrekt ist. Es ist Chrom, das sich hier auf fehlerhafte Weise verhält, daher sollten wir die Isolationseigenschaft festlegen lassen, falls der Fehler behoben wird.
Okay, aber wir möchten, dass dies nur dann geschieht, wenn der Link fokussiert oder schwebt. Ansonsten ist das Pseudoelement nicht sichtbar-sagen wir, es ist auf nichts verkleinert.
A { / * wie früher */ Textdekoration: Keine; &::nach { / * wie früher */ Transformation: Skala (0); } &: FOCUS {SUCLINE: Keine} &: Focus &: Hover {& :: After {Transform: None; }} }
Wir haben auch die Link -Unterstreichung und den Fokusumriss entfernt. Im Folgenden können Sie nun den Differenzeffekt auf: HOVER sehen (der gleiche Effekt tritt auf: Fokus, was Sie in der Live -Demo testen können).
Wir haben jetzt unsere Staatsänderung, aber es sieht rau aus, also fügen wir einen Übergang hinzu!
A { / * wie früher */ &::nach { / * wie früher */ Übergang: 25s transformieren; } }
Viel besser!
Es würde noch besser aussehen, wenn unser Pseudo nicht aus nichts in der Mitte, sondern von einer dünnen Linie unten wuchs. Dies bedeutet, dass wir das Transform-Origin auf der Unterkante (bei 100% vertikal und horizontal) festlegen und anfänglich unseren Pseudo auf etwas mehr als nur nichts entlang der Y- Achse skalieren müssen.
A { / * wie früher */ &::nach { / * wie früher */ Transform-Origin: 0 100%; Transformation: Scaley (.05); } }
Etwas anderes, das ich hier tun würde, ist, die Schrift des Absatzes durch eine ästhetischere zu ersetzen. Achten Sie also auch darum! Aber jetzt haben wir ein anderes Problem: Das Ende des 'D' steckt aus dem Rechteck auf: FOCUS/: HOVER.
Wir können dies mit einer horizontalen Polsterung auf unserem Link beheben.
A { / * wie früher */ Polsterung: 0 .25em; }
Falls Sie sich fragen, warum wir diese Polsterung sowohl nach rechts als auch auf der linken Seite festlegen, anstatt nur ein Polsterrecht zu setzen, ist der Grund unten dargestellt. Wenn unser Link-Text zu einer „außerirdischen Welt“ wird, würde der lockige Start des 'A' außerhalb unseres Rechtecks enden, wenn wir keine Polsterlinks hätten.
Diese Demo mit einem oben genannten Mehrwertverbindungslink zeigt auch ein weiteres Problem, wenn wir die Ansichtsfensterbreite reduzieren.
Eine schnelle Lösung wäre hier, das Display festzulegen: Inline-Block auf dem Link. Dies ist keine perfekte Lösung. Es bricht auch, wenn der Link -Text länger als die Ansichtsfensterbreite ist, aber er funktioniert in diesem speziellen Fall. Lassen Sie ihn also jetzt hier und wir werden in dieser Zeit zu diesem Problem zurückkehren.
Betrachten wir nun die Situation eines leichten Themas. Da es keine Möglichkeit gibt, für den Link -Text weiß anstelle von schwarz zu werden: schweben Sie oder: Fokus, indem Sie zwei identische Highlight -Ebenen mischen, die beide nicht weiß sind, benötigen wir hier einen anderen Ansatz, bei dem es nicht darum geht, nur Mischmodi zu verwenden.
Was wir in diesem Fall tun, ist, zunächst den Hintergrund, den normalen Absatz -Textfarbe und die Link -Textfarbe auf die gewünschten Werte festgelegt zu haben, aber invertiert . Ich habe diese Inversion anfangs manuell gemacht, aber dann hatte ich den Vorschlag, die Sass Invert () -Funktion zu verwenden, was eine sehr coole Idee ist, die die Dinge wirklich vereinfacht. Nachdem wir dieses dunkle Thema haben, das im Grunde das helle Thema ist, das wir invertiert haben, erhalten wir unser gewünschtes Ergebnis, indem wir alles mit Hilfe der CSS Invert () -Filterfunktion wieder invertieren.
Tiny Caace hier: Wir können den Filter nicht einstellen: Invert (1) auf den Körper- oder HTML -Elementen, da dies nicht so verhalten wird, wie wir es erwarten, und wir werden nicht das gewünschte Ergebnis erzielen. Aber wir können sowohl den Hintergrund als auch den Filter auf einen Wrapper um unseren Absatz setzen.
<abschnitt> <p> Hallo, <a href="'#'"> Alien World </a>! </p> </abschnitt>
Körper { /* gleich wie zuvor, Ohne den Ort, den Inhalt, den Hintergrund und die Farbdeklarationen, was wir im Abschnitt */ bewegen } Abschnitt { Anzeige: Grid; Ort-in-intent: Zentrum; Hintergrund: Invert (#ddd) / * SASS invert (<farben>) Funktion * /; Farbe: Invert (#222); / * SASS Invert <farben>) Funktion */; Filter: Invert (1); / * CSS -Filter invert (<nummer prozentsatz>) Funktion */ } A { / * wie früher */ Farbe: invertiert (lila); / * SASS Invert (<farben>) Funktion */ }</farben></nummer></farben></farben>
Hier ist ein Beispiel für eine Navigationsleiste, die diesen Effekt verwendet (und eine Reihe anderer cleverer Tricks, aber diese liegen außerhalb des Rahmens dieses Artikels). Wählen Sie eine andere Option aus, um sie in Aktion anzuzeigen:
Etwas anderes, mit dem wir vorsichtig sein müssen, ist Folgendes: Alle Nachkommen unseres Abschnitts werden invertiert, wenn wir diese Technik anwenden. Und das ist wahrscheinlich nicht das, was wir im Fall von IMG -Elementen wollen - ich erwarte sicherlich nicht, die Bilder in einem Blog -Beitrag invertiert zu sehen, wenn ich von der Dunkelheit zum leichten Thema wechsle. Folglich sollten wir die Filterinversion bei jedem IMG -Nachkomme unseres Abschnitts umkehren.
Abschnitt { / * wie früher */ &, & img {filter: invert (1); } }
Wenn Sie alles zusammenstellen, zeigt die folgende Demo sowohl die dunklen als auch die hellen Themenfälle mit Bildern:
Kehren wir nun zum Problem mit dem Wraping-Link-Text zurück und sehen, ob wir keine besseren Optionen haben, als die A-Elemente inline-Blocks zu machen.
Nun, das tun wir! Wir können zwei Hintergrundschichten mischen, anstatt den Textinhalt und einen Pseudo zu mischen. Eine Schicht wird in den Text abgeschnitten, während die andere in die Grenzbox und seine vertikale Größe anfänglich in den schwebenden und fokussierten Fällen zwischen 5% und 100% abgeschnitten wird.
A { / * wie früher */ -Webkit-Text-Fill-Farben: transparent; -moz-text-fill-color: transparent; -Full: Linear Gradient (CurrentColor, CurrentColor); Hintergrund: var (-voll), var (-voll) 0 100%/1%var (-Sy, 5%) Repeat-X; -Webkit-Background-Clip: Text, Border-Box; Hintergrund-Clip: Text, Border-Box; Hintergrund-Blend-Mode: Differenz; Übergang: Hintergrundgröße .25s; &: Focus &: Hover { - -sy: 100%; } }
Beachten Sie, dass wir nicht einmal mehr einen Pseudoelement haben, also haben wir einige der CSS darauf aufgenommen, ihn auf den Link selbst verschoben und es für diese neue Technik gepasst. Wir haben von der Verwendung von Mix-Blend-Mode zur Verwendung des Hintergrund-Blend-Modus gewechselt. Wir wechseln jetzt die Hintergrundgröße der Transformation und, in der: Fokus und: Schwebezustände; Und wir ändern jetzt nicht die Transformation, sondern eine benutzerdefinierte Eigenschaft, die die vertikale Komponente der Hintergrundgröße darstellt.
Viel besser, obwohl dies auch keine perfekte Lösung ist.
Das erste Problem ist eines, das Sie sicherlich bemerkt haben, wenn Sie den Live -Demo -Link der Bildunterschrift in Firefox überprüft haben: Es funktioniert überhaupt nicht. Dies liegt an einem Firefox -Fehler, den ich 2018 anscheinend gemeldet habe, und vergaß dann alles, bis ich anfing, mit Mischmodi zu spielen und ihn erneut zu treffen.
Das zweite Problem ist eines, das in der Aufnahme spürbar ist. Die Links scheinen etwas verblasst zu sein. Dies liegt daran, dass Chrome-Mischelemente aus irgendeinem Grund Inline-Elemente wie Links (beachten Sie, dass dies bei Blockelementen wie Divs nicht passieren wird) mit dem Hintergrund ihres nächsten Vorfahren (in diesem Fall der Abschnitt), wenn diese Inline-Elemente Hintergrund-Blend-Modus auf irgendetwas anderes als normal eingestellt haben.
Noch seltsamer: Isolation Isolation: Isolieren Sie den Link oder seinen übergeordneten Absatz nicht. Ich hatte immer noch ein nagiges Gefühl, dass es etwas mit dem Kontext zu tun hat, also habe ich beschlossen, weiterhin mögliche Hacks darauf zu werfen, und hoffe, vielleicht funktioniert etwas. Nun, ich musste nicht viel Zeit damit verbringen. Setzen Sie die Opazität auf einen Unterreden (aber immer noch nahe genug bis 1, sodass es nicht erkennbar ist, dass es nicht vollständig undurchsichtig ist). Wert behebt es.
A { / * wie früher */ Deckkraft: .999; / * Hack, um das Mischungsproblem zu beheben ¯_ (ツ) _/¯ */ }
Das letzte Problem ist ein weiteres, der in der Aufnahme spürbar ist. Wenn Sie sich das 'R' am Ende von „Amur“ ansehen, können Sie feststellen, dass sein rechtes Ende herausgeschnitten ist, wenn es außerhalb des Hintergrund -Rechtecks fällt. Dies ist insbesondere auffällig, wenn Sie es mit dem 'R' in "Leopard" vergleichen.
Ich hatte keine großen Hoffnungen, diese zu beheben, warf die Frage trotzdem zu Twitter. Und was weißt du, es kann repariert werden! Die Verwendung von Box-Decoration-Break in Kombination mit der Polsterung, die wir bereits festgelegt haben, kann uns helfen, den gewünschten Effekt zu erzielen!
A { / * wie früher */ Box-Decoration-Break: Klon; }
Beachten Sie, dass die Abschlüsse des Box-Abschlusses für alle Webkit-Browser--webkit-Präfix noch benötigt. Im Gegensatz zu Eigenschaften wie Hintergrundclip, bei denen mindestens ein Wert Text ist, können automatische Präfixing-Tools das Problem einfach einwandfrei kümmern. Deshalb habe ich die vorangestellte Version nicht in den obigen Code aufgenommen.
Ein weiterer Vorschlag, den ich bekam, war, eine negative Marge hinzuzufügen, um die Polsterung auszugleichen. Ich gehe in diesem Fall hin und her - ich kann nicht entscheiden, ob mir das Ergebnis besser mit oder ohne es gefällt. In jedem Fall ist es eine erwähnte Option.
$ p: .25em; A { / * wie früher */ Marge: 0 (-$ P); / * Wir haben es in die Klammung gesteckt, damit Sass nicht versucht, Subtraktion auszuführen */ Polsterung: 0 $ P; }
Trotzdem muss ich zugeben, dass die Animation der Hintergrundposition oder die Hintergrundgröße eines Gradienten etwas langweilig ist. Aber dank Houdini können wir jetzt kreativ und animieren, was wir uns wünschen, obwohl dies im Moment nur in Chromium unterstützt wird. Zum Beispiel der Radius eines radialen Gradienten () wie unten oder der Fortschritt eines Kegelgradienten ().
Dies ist die Art von Effekt, die ich oft durch die Verwendung von Element-Duplikation sehe-die beiden Kopien werden übereinander geschichtet, wobei einer von ihnen einen Invert-Filter hat und auf der oberen Seite verwendet wird, um beide Schichten anzuzeigen. Eine andere Route ist ein zweites Element mit einem Alpha, das niedrig genug ist.
Beide Ansätze erledigen die Aufgabe, wenn wir einen Teil des gesamten Elements mit all seinen Inhalten und Nachkommen invertieren möchten, aber sie können uns nicht helfen, wenn wir nur einen Teil des Hintergrunds umkehren möchten-sowohl Filter- als auch Hintergrundfilter beeinflussen ganze Elemente, nicht nur ihre Hintergründe. Und während die neue Filter () -Funktion (bereits von Safari unterstützt) ausschließlich auf Hintergrundschichten wirkt, wirkt sich dies auf den gesamten Bereich des Hintergrunds aus, nicht nur ein Teil davon.
Hier kommt die Mischung ins Spiel. Die Technik ist ziemlich einfach: Wir haben eine Hintergrundschicht, von der wir umkehren möchten, und eine oder mehrere Gradientenschichten, die uns einen weißen Bereich geben, in dem wir die andere Schicht und Transparenz (oder Schwarz) inversion wollen. Dann mischen wir mit einem der beiden heute diskutierten Mischmodi. Zum Zweck der Inversion bevorzuge ich Ausschluss (ein Charakter ist kürzer als Unterschied).
Hier ist ein erstes Beispiel. Wir haben ein quadratisches Element, das einen zweischichtigen Hintergrund hat. Die beiden Schichten sind ein Bild einer Katze und einen Gradienten mit einem scharfen Übergang zwischen Weiß und Transparent.
div { Hintergrund: Lineargradient (45 Grad, weiß 50%, transparent 0), URL (CAT.JPG) 50%/ Deckung; }
Dies gibt uns das folgende Ergebnis. Wir haben auch Dimensionen, einen Border-Radius, Schatten und den Text festgelegt, im Prozess, aber in diesem Zusammenhang ist alles nicht wirklich wichtig:
Als nächstes brauchen wir nur noch eine CSS -Erklärung, um die untere linke Hälfte umzukehren:
div { / * wie früher */ Hintergrund-Blend-Mode: Ausschluss; / * oder Differenz, aber es ist 1 char länger */ }
Beachten Sie, wie der Text nicht durch Inversion beeinflusst wird. Es wird nur auf den Hintergrund angewendet.
Sie kennen wahrscheinlich die interaktiven Vor- und Nachher-Bild-Schieberegler. Vielleicht haben Sie hier auf CSS-Tricks sogar etwas gesehen. Ich habe es auf compressor.io gesehen, mit dem ich oft Bilder komprimiert habe, einschließlich der in diesen Artikeln verwendeten!
Unser Ziel ist es, mit einem einzigen HTML -Element unter 100 Bytes JavaScript etwas der Art zu erstellen - und nicht einmal viel CSS!
Unser Element wird ein Bereichseingang sein. Wir setzen seine min- oder maximalen Attribute nicht fest, daher standardmäßig 0 bzw. 100. Wir haben das Wertattribut auch nicht festgelegt, daher ist es standardmäßig 50, was auch der Wert ist, den wir eine benutzerdefinierte Eigenschaft angeben, -K, in seinem Style -Attribut festgelegt.
<eingabe type="'Bereich'" style="'-k:"></eingabe>
In der CSS beginnen wir mit einem Basisrücksatz, dann machen wir unsere Eingabe zu einem Blockelement, das die gesamte Ansichtsfensterhöhe einnimmt. Wir geben auch Dimensionen und Dummy -Hintergründe für die Strecke und den Daumen, damit wir sofort Dinge auf dem Bildschirm sehen können.
$ thumb-w: 5em; @mixin track () { Grenze: Keine; Breite: 100%; Höhe: 100%; Hintergrund: URL (Blumen.JPG) 50%/ Deckung; } @mixin thumb () { Grenze: Keine; Breite: $ thumb-w; Höhe: 100%; Hintergrund: lila; } * {{ Rand: 0; Polsterung: 0; } [Typ = 'Bereich'] { &, & ::-Webkit-Slider-Damb,, & ::-webkit-slider-runnable-track {-webkit-upearance: keine; } Anzeige: Block; Breite: 100VW; Höhe: 100VH; & ::-webkit-Slider-Runnable-Track {@include Track; } & ::-Moz-Range-Track {@include Track; } & ::-webkit-Slider-Thumb {@include thumb; } & ::-Moz-Range-Thumb {@include Thumb; } }
Der nächste Schritt besteht darin, eine weitere Hintergrundschicht auf der Spur hinzuzufügen, einen linearen Gradienten, bei dem die Trennlinie zwischen Transparent und Weiß vom Strombereicheingangswert abhängt-K, und dann die beiden mischen.
@mixin track () { / * wie früher */ Hintergrund: URL (Blumen.JPG) 50%/ Deckung, linearer Gradient (90 °, transparenter var (-p), weiß 0); Hintergrund-Blend-Mode: Ausschluss; } [Typ = 'Bereich'] { / * wie früher */ --P: Calc (var (-k) * 1%); }
Beachten Sie, dass die Reihenfolge der beiden Hintergrundschichten der Spur keine Rolle spielt, da sowohl Ausschluss als auch Unterschied kommutativ sind.
Es sieht aus wie etwas, aber das Ziehen des Daumen macht nichts, um die Trennlinie zu bewegen. Dies geschieht, weil der aktuelle Wert, -K (von dem die Trennlinienposition des Gradienten, - -P, abhängig) nicht automatisch aktualisiert wird. Lassen Sie uns dies mit einem kleinen Stück JavaScript beheben, das den Schieberegler bei der Änderung erhält und dann auf diesen Wert setzt.
AddEventListener ('Eingabe', e => { sei _t = e.target; _t.style.setProperty ('-k', _t.value) })
Jetzt scheint alles einwandfrei zu funktionieren!
Aber ist es wirklich? Nehmen wir an, wir tun etwas Lustigeres für den Daumenhintergrund:
$ thumb-r: .5*$ thumb-w; $ thumb-l: 2px; @mixin thumb () { / * wie früher */ -List: #fff 0% 60 Grad, transparent 0%; Hintergrund: Conic-Gradient (ab 60 °, var (-Liste)) 0/37,5%/ * Linkspfeil */,, Conic-Gradient (ab 240 Grad, var (-Liste)) 100%/37,5%/ * Rechtspfeil */,,, Radialgradient (Kreis, Kreis, transparente Calc ( #{$ thumb -r} - #{$ thumb -l} - 1px) / * im Kreis * /,,,,,, #fff calc (#{$ thumb-r}-#{$ thumb-l}) calc (#{$ thumb-r}-1px) / * Circle Line * /,,, transparent $ thumb-r / * Außenkreis * /), linearer Gradient ( #fff calc (50%- #{$ thumb-r} .5* #{$ thumb-l}) /*Top Line* /,,, transparent 0 calc (50% #{$ thumb-r}-.5* #{$ thumb-l}) /*Lücke hinter dem Kreis* /,,, #fff 0/ * Fazit */) 50% 0/ #{$ thumb-l}; Hintergrundrepeat: No-Repeat; }
Der lineare Gradient () erstellt die dünne vertikale Trennlinie, die Radialgradient () erstellt den Kreis, und die beiden Schichten von Conic-Gradient () erzeugen die Pfeile.
Das Problem ist jetzt offensichtlich, wenn Sie den Daumen von einem Ende zum anderen ziehen: Die Trennlinie bleibt nicht an der vertikalen Mittellinie des Daumens festgelegt.
Wenn wir--P auf Calc (var (-k)*1%) einstellen, bewegt sich die Trennlinie von 0%auf 100%. Es sollte sich wirklich von einem Ausgangspunkt bewegt, der eine halbe Daumenbreite $, $ thumb-r, bis eine halbe Daumenbreite vor 100%ist. Das heißt, innerhalb eines Bereichs, der zu 100% minus eine Daumenbreite ist, $ taumsw-w. Wir subtrahieren eine Hälfte von jedem Ende, also ist das eine ganze Daumenbreite, die abgezogen werden muss. Lasst uns das beheben!
--P: Calc ( #{$ thumb-r} var (-k) * (100%- #{$ thumb-w}) / 100);
Viel besser!
Aber die Art und Weise, wie die Bereichseingaben funktionieren, ihre Grenzkasten bewegt sich innerhalb der Grenzen der Inhaltsbox der Spur (Chrome) oder innerhalb der Grenzen der Inhaltsbox der tatsächlichen Eingabe (Firefox) ... das fühlt sich immer noch nicht richtig an. Es würde viel besser aussehen, wenn die Mittellinie des Daumens (und folglich die Trennlinie) bis zu den Ansichtsfensterkanten gehen würde.
Wir können nicht ändern, wie die Eingänge der Reichweite funktionieren, aber wir können die Eingabe außerhalb des Ansichtsfensters um eine halbe Daumenbreite links und um eine weitere halbe Daumenbreite nach rechts erstrecken. Dies macht seine Breite dem des Ansichtsfensters 100VW und einer ganzen Daumenbreite, $ thumb-w.
Körper {Überlauf: versteckt; } [Typ = 'Bereich'] { / * wie früher */ Margin-Links:-$ thumb-r; Breite: Calc (100VW #{$ thumb-w}); }
Noch ein paar hübsche Verbesserungen im Zusammenhang mit dem Cursor und das war's!
Eine schickere Version davon (inspiriert von der Website compressor.io) besteht darin, die Eingabe in eine Karte zu setzen, deren 3D -Rotation sich auch ändert, wenn sich die Maus darüber bewegt.
Wir könnten auch einen vertikalen Schieberegler verwenden. Dies ist etwas komplexer, da unsere einzige zuverlässige Cross-Browser-Methode, um benutzerdefinierte vertikale Schieberegler zu erstellen, darin besteht, eine Rotation auf sie anzuwenden, aber dies würde auch den Hintergrund drehen. Was wir tun, ist, den - -P -Wert und diese Hintergründe auf dem (nicht gedrehten) Schieberegehre zu setzen und dann den Eingang und seine Spur vollständig transparent zu halten.
Dies ist in der Demo unten in Aktion zu sehen, wo ich ein Foto von mir invertreiche, das meinen geliebten Kreator -Hoodie zeigt.
Wir können natürlich auch einen radialen Gradienten () für einen coolen Effekt verwenden:
Hintergrund: Radialgradient (Kreis bei var (-x, 50%) var (-y, 50%), #000 Calc (var (-Card-r)-1px), #fff var (-card-r)) Border-Box, $ IMG 50%/ Deckung;
In diesem Fall wird die von den benutzerdefinierte Eigenschaften --x und - -y angegebene Position aus der Mausbewegung über der Karte berechnet.
Der umgekehrte Bereich des Hintergrunds muss nicht unbedingt von einem Gradienten erstellt werden. Es kann auch der Bereich hinter dem Text eines Überschriftens sein, wie in diesem älteren Artikel über den kontrastierenden Text mit einem Hintergrundbild gezeigt.
Die Mischtechnik zur Inversion ist leistungsfähiger als die Verwendung von Filtern in mehr als einer Weise. Es ermöglicht uns auch, den Effekt allmählich auf einem Gradienten anzuwenden. Zum Beispiel ist die linke Seite überhaupt nicht invertiert, aber dann gehen wir nach rechts bis zur vollen Inversion.
Um zu verstehen, wie wir diesen Effekt erhalten, müssen wir zunächst verstehen, wie der Invert (P) -Effekt (P) Effekt erhalten kann, wobei P im Intervall [0%, 100%] (oder im [0, 1] -Intervall, wenn wir die Dezimalpräsentation verwenden), einen Wert sein kann.
Die erste Methode, die sowohl für den Unterschied als auch für den Ausschluss funktioniert, besteht darin, den Alpha -Kanal unseres Weißs auf P zu setzen. Dies ist in der Demo unten in Aktion zu sehen, wo das Ziehen des Schiebereglers den Fortschritt der Bevölkerung steuert:
Falls Sie sich über die HSL -Notation wundern (0, 0%, 100% / 100%), ist dies nun ein gültiger Weg, um ein Weiß mit einem Alpha von 1 zu repräsentieren.
Darüber hinaus funktioniert der Filter: Invert (P) im allgemeinen Fall (dh jeden Kanalwert auf ein gequetschtes Intervall [min (p, q), Max (p, q)]), wobei Q das Komplement von P (oder q = 1 - P) vor dem Umkehrung (Subtrahieren von 1).
1 - (q ch · (p - q)) = = 1 - (1 - p ch · (p - (1 - p)) = = 1 - (1 - p ch · (2 · p - 1)) = = 1 - (1 - P 2 · ch · p - ch) = = 1 - 1 p - 2 · ch · p ch = = Ch p - 2 · ch · p
Was wir bekommen haben, ist genau die Formel für den Ausschluss, bei dem der andere Kanal P ist! Daher können wir den gleichen Effekt wie Filter erzielen: Invert (P) für jeden P im [0%, 100%] -Vervall mit dem Ausschlussmischmodus, wenn die andere Schicht RGB (P, P, P) ist.
Dies bedeutet, dass wir eine allmähliche Inversion entlang eines linearen Gradienten () haben können, der von der linken Kante von No-Inversion zu einer vollen Inversion entlang der rechten Kante führt) mit Folgendem:
Hintergrund: URL (Butterfly_blues.jpg) 50%/ Deckung, linearer Gradient (90 Grad,, #000 / * äquivalent zu RGB (0%, 0%, 0%) und HSL (0, 0%, 0%) * /,. #FFF / * Äquivalent zu RGB (100%, 100%, 100%) und HSL (0, 0%, 100%) * /); Hintergrund-Blend-Mode: Ausschluss;
Beachten Sie, dass die Verwendung eines Gradienten von Schwarz zu Weiß zur schrittweisen Inversion nur mit dem Ausschlussmischmodus und nicht mit dem Unterschied funktioniert. Das Ergebnis, das in diesem Fall in diesem Fall in seiner Formel erzeugt wird, ist eine Pseudo -allmähliche Inversion, die nicht durch das 50% Grau in der Mitte fließt, aber durch RGB -Werte, bei denen jedes der drei Kanäle an verschiedenen Punkten entlang des Gradienten auf Null gesetzt sind. Deshalb sieht der Kontrast stark aus. Es ist auch ein bisschen künstlerischer, aber das ist nicht wirklich etwas, über das ich eine Meinung habe.
Es muss nicht unbedingt von einem schwarzen bis weißen Gradienten stammen. Es kann auch von einem Schwarzweißbild stammen, da die schwarzen Bereiche des Bildes die Hintergrundfarbe bewahren würden, die weißen Bereiche es vollständig umkehren und wir eine teilweise Inversion für alles dazwischen haben würden, wenn der Ausschlussmischungsmodus verwendet wird. Der Unterschied würde uns wieder ein starkes Duotone -Ergebnis geben.
Dies ist in der folgenden interaktiven Demo zu sehen, in der Sie die Hintergrundfarbe ändern und die Trennlinie zwischen den von den beiden Mischmodi erzeugten Ergebnissen ziehen können.
Die Grundidee hier ist, dass wir zwei Schichten mit nur schwarzen und weißen Pixeln haben.
Let's consider an element with two pseudos, each having a background that's a repeating CSS gradient with sharp stops:
$d: 15em; $u0: 10%; $u1: 20%; div { &::before, &::after { Anzeige: Inline-Block; width: $d; height: $d; background: repeating-radial-gradient(#000 0 $u0, #fff 0 2*$u0); Inhalt: ''; } &::nach { background: repeating-conic-gradient(#000 0% $u1, #fff 0% 2*$u1); } }
Depending on the browser and the display, the edges between black and white may look jagged… or not.
Just to be on the safe side, we can tweak our gradients to get rid of this issue by leaving a tiny distance, $e, between the black and the white:
$u0: 10%; $e0: 1px; $u1: 5%; $e1: .2%; div { &::before { Hintergrund: repeating-radial-gradient( #000 0 calc(#{$u0} - #{$e0}), #fff $u0 calc(#{2*$u0} - #{$e0}), #000 2*$u0); } &::nach { Hintergrund: repeating-conic-gradient( #000 0% $u1 - $e1, #fff $u1 2*$u1 - $e1, #000 2*$u1); } }
Then we can place them one on top of the other and set mix-blend-mode to exclusion or difference, as they both produce the same result here.
div { &::before, &::after { /* same other styles minus the now redundant display */ Position: absolut; mix-blend-mode: exclusion; } }
Wherever the top layer is black, the result of the blending operation is identical to the other layer, whether that's black or white. So, black over black produces black, while black over white produces white.
Wherever the top layer is white, the result of the blending operation is identical to the other layer inverted. So, white over black produces white (black inverted), while white over white produces black (white inverted).
However, depending on the browser, the actual result we see may look as desired (Chromium) or like the ::before got blended with the greyish background we've set on the body and then the result blended with the ::after (Firefox, Safari).
The way Chromium behaves is a bug, but that's the result we want. And we can get it in Firefox and Safari, too, by either setting the isolation property to isolate on the parent div (demo) or by removing the mix-blend-mode declaration from the ::before (as this would ensure the blending operation between it and the body remains the default normal, which means no blending) and only setting it on the ::after (demo).
Of course, we can also simplify things and make the two blended layers be background layers on the element instead of its pseudos. This also means switching from mix-blend-mode to background-blend-mode.
$d: 15em; $u0: 10%; $e0: 1px; $u1: 5%; $e1: .2%; div { width: $d; height: $d; Hintergrund: repeating-radial-gradient( #000 0 calc(#{$u0} - #{$e0}), #fff $u0 calc(#{2*$u0} - #{$e0}), #000 2*$u0), repeating-conic-gradient( #000 0% $u1 - $e1, #fff $u1 2*$u1 - $e1, #000 2*$u1);; background-blend-mode: exclusion; }
This gives us the exact same visual result, but eliminates the need for pseudo-elements, eliminates the potential unwanted mix-blend-mode side effect in Firefox and Safari, and reduces the amount of CSS we need to write.
The basic idea is we have a scene that's half black and half white, and a white item moving from one side to the other. The item layer and the scene layer get then blended using either difference or exclusion (they both produce the same result).
When the item is, for example, a ball, the simplest way to achieve this result is to use a radial-gradient for it and a linear-gradient for the scene and then animate the background-position to make the ball oscillate.
$d: 15em; div { width: $d; height: $d; Hintergrund: radial-gradient(closest-side, #fff calc(100% - 1px), transparent) 0/ 25% 25% no-repeat, linear-gradient(90deg, #000 50%, #fff 0); background-blend-mode: exclusion; animation: mov 2s ease-in-out infinite alternate; } @keyframes mov { to { background-position: 100%; }}
We can also make the ::before pseudo the scene and the ::after the moving item:
$d: 15em; div { Anzeige: Grid; width: $d; height: $d; &::before, &::after { grid-area: 1/ 1; background: linear-gradient(90deg, #000 50%, #fff 0); Inhalt: ''; } &::nach { place-self: center start; padding: 12.5%; Grenzradius: 50%; Hintergrund: #fff; mix-blend-mode: exclusion; animation: mov 2s ease-in-out infinite alternate; } } @keyframes mov { to { transform: translate(300%); }}
This may look like we're over-complicating things considering that we're getting the same visual result, but it's actually what we need to do if the moving item isn't just a disc, but a more complex shape, and the motion isn't just limited to oscillation, but it also has a rotation and a scaling component.
$d: 15em; $t: 1s; div { /* same as before */ &::nach { /* same as before */ /* creating the shape, not detailed here as it's outside the scope of this article */ @include poly; /* the animations */ Animation: t $t ease-in-out infinite alternate, r 2*$t ease-in-out infinite, s .5*$t ease-in-out infinite alternate; } } @keyframes t { to { translate: 300% } } @keyframes r { 50% { rotate: .5turn; } 100% { rotate: 1turn;; } } @keyframes s { to { scale: .75 1.25 } }
Note that, while Safari has now joined Firefox in supporting the individual transform properties we're animating here, these are still behind the Experimental Web Platform features flag in Chrome (which can be enabled from chrome://flags as shown below).
We won't be going into details about the “how” behind these demos as the basic idea of the blending effect using exclusion or difference is the same as before and the geometry/animation parts are outside the scope of this article. However, for each of the examples below, there is a link to a CodePen demo in the caption and a lot of these Pens also come with a recording of me coding them from scratch.
Here's a crossing bars animation I recently made after a Bees & Bombs GIF:
And here's a looping moons animation from a few years back, also coded after a Bees & Bombs GIF:
We're not necessarily limited to just black and white. Using a contrast filter with a subunitary value (filter: contrast(.65) in the example below) on a wrapper, we can turn the black into a dark grey and the white into a light grey:
Here's another example of the same technique:
If we want to make it look like we have a XOR effect between black shapes on a white background, we can use filter: invert(1) on the wrappers of the shapes, like in the example below:
And if we want something milder like dark grey shapes on a light grey background, we don't go for full inversion, but only for partial one. This means using a subunitary value for the invert filter like in the example below where we use filter: invert(.85):
It doesn't necessarily have to be something like a looping or loading animation. We can also have a XOR effect between an element's background and its offset frame. Just like in the previous examples, we use CSS filter inversion if we want the background and the frame to be black and their intersection to be white.
Another example would be having a XOR effect on hovering/ focusing and clicking a close button. The example below shows both night and light theme cases:
Things can look a bit sad only in black and white, so there are few things we can do to put some life into such demos.
The first tactic would be to use filters. We can break free from the black and white constraint by using sepia() after lowering the contrast (as this function has no effect over pure black or white). Pick the hue using hue-rotate() and then fine tune the result using brightness() and saturate() or contrast().
For example, taking one of the previous black and white demos, we could have the following filter chain on the wrapper:
Filter: contrast(.65) /* turn black and white to greys */ sepia(1) /* retro yellow-brownish tint */ hue-rotate(215deg) /* change hue from yellow-brownish to purple */ blur(.5px) /* keep edges from getting rough/ jagged */ contrast(1.5) /* increase saturation */ brightness(5) /* really brighten background */ contrast(.75); /* make triangles less bright (turn bright white dirty) */
For even more control over the result, there's always the option of using SVG filters.
The second tactic would be to add another layer, one that's not black and white. For example, in this radioactive pie demo I made for the first CodePen challenge of March, I used a purple ::before pseudo-element on the body that I blended with the pie wrapper.
body, div { display: grid; } /* stack up everything in one grid cell */ div, ::before { grid-area: 1/ 1; } body::before { background: #7a32ce; } /* purple layer */ /* applies to both pie slices and the wrapper */ div { mix-blend-mode: exclusion; } .a2d { background: #000; } /* black wrapper */ .pie { background: /* variable size white pie slices */ conic-gradient(from calc(var(--p)*(90deg - .5*var(--sa)) - 1deg), transparent, #fff 1deg calc(var(--sa) var(--q)*(1turn - var(--sa))), transparent calc(var(--sa) var(--q)*(1turn - var(--sa)) 1deg)); }
This turns the black wrapper purple and the white parts green (which is purple inverted).
Another option would be blending the entire wrapper again with another layer, this time using a blend mode different from difference or exclusion. Doing so would allow us more control over the result so we're not limited to just complementaries (like black and white, or purple and green). That, however, is something we'll have to cover in a future article.
Finally, there's the option of using difference (and not exclusion) so that we get black where two identical (not necessarily white) layers overlap. For example, the difference between coral and coral is always going to be 0 on all three channels, which means black. This means we can adapt a demo like the offset and XOR frame one to get the following result:
With some properly set transparent borders and background clipping, we can also make this work for gradient backgrounds:
Similarly, we can even have an image instead of a gradient!
Note that this means we also have to invert the image background when we invert the element in the second theme scenario. But that should be no problem, because in this article we've also learned how to do that: by setting background-color to white and blending the image layer with it using background-blend-mode: exclusion!
Just these two blend modes can help us get some really cool results without resorting to canvas, SVG or duplicated layers. But we've barely scratched the surface here. In future articles, we'll dive into how other blend modes work and what we can achieve with them alone or in combination with previous ones or with other CSS visual effects such as filters. And trust me, the more tricks you have up your sleeve, the cooler the results you're able to achieve get!
Das obige ist der detaillierte Inhalt vonZähmung Mischmodi: 'Differenz' und 'Ausschluss'. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!