Ich bin kürzlich auf einen coolen Effekt gestoßen, der als Glassmorphismus in einem Dribble -Schuss bekannt ist. Mein erster Gedanke war, dass ich es in ein paar Minuten schnell nachbilden konnte, wenn ich nur ein paar Emojis für die Ikonen benutze, ohne die Zeit für SVG-Inging zu verschwenden.
Ich hätte mich nicht mehr in diesen „wenigen Minuten“ falsch machen können - sie waren Tage, in denen sie wütend und frustrierend an diesem Juckreiz kratzten!
Es stellt sich heraus, dass es jedoch Ressourcen gibt, wie CSS ein solcher Effekt vorhanden ist, aber alle annehmen, dass die Überlagerung rechteckig ist oder höchstens ein Rechteck mit randlichem Radius. Es ist jedoch viel komplizierter als erwartet, dass es sich lohnt, den Prozess zu teilen, die Fallen, die ich auf dem Weg gelernt habe. Und auch die Dinge, die ich immer noch nicht verstehe.
Kurze Antwort: Weil SVG zu viel Zeit braucht. Lange Antwort: Weil mir das künstlerische Gefühl fehlt, sie einfach in einen Bildredakteur zu zeichnen, aber ich bin mit der Syntax so vertraut, dass ich oft vorgefertigte SVGs zu weniger als 10% ihrer ursprünglichen Größe finde. Ich kann sie also nicht einfach verwenden, da ich sie im Internet finde - ich muss den Code wiederholen, um ihn super sauber und kompakt zu machen. Und das braucht Zeit. Viel Zeit, weil es detaillierte Arbeit ist.
Und wenn ich nur ein Menükonzept mit Symbolen schnell codieren möchte, greife ich mit Emojis zurück und wende einen Filter auf sie an, um sie mit dem Thema übereinzustimmen, und das war's! Es ist das, was ich für diese Demo für flüssige Registerkarteninteraktion getan habe - diese Symbole sind alle Emojis! Der glatte Valley -Effekt verwendet die Maskenkompositionstechnik.
Okay, das wird unser Ausgangspunkt sein: Verwenden von Emojis für die Ikonen.
Mein erster Gedanke war, die beiden Pseudos (mit Emoji -Inhalten) der Navigationsverbindungen zu stapeln, leicht versetzt und die untere mit einer Transformation zu drehen, damit sie sich nur teilweise überlappen. Dann würde ich den oberen Semitransparent mit einem Deckkraftwert kleiner als 1 machen, den Hintergrund-Filter () () darauf einstellen, und das sollte gerade genug sein.
Nachdem Sie das Intro gelesen haben, haben Sie wahrscheinlich herausgefunden, dass dies nicht wie geplant verlief, aber lassen Sie uns sehen, wie es in Code aussieht und welche Probleme es damit gibt.
Wir erzeugen die Navigationsleiste mit dem folgenden Mops:
- sei data = { - Home: {ICO: '?', Hue: 200}, - Hinweise: {ICO: '? umpf', Hue: 260}, - Aktivität: {ICO: '?', Hue: 320}, - Entdeckung: {ICO: '?', Hue: 30} -}; - sei E = Object.Entries (Daten); - Sei n = E.Length; Navigation - für (lass i = 0; i> n; i) a (href = ' #' data-ICO = e [i] [1] .ICO style = `--hue: $ {e [i] [1] .hue} Deg`) #{e [i] [0]}
Welche zum HTML unten kompiliert:
<nav> <a href="'#'" data-ico="'?'" style="'-hue:"> home </a> <a href="'#'" data-ico="'?" style="'-hue:"> Notizen </a> <a href="'#'" data-ico="'?'" style="'-hue:"> Aktivität </a> <a href="'#'" data-ico="'?'" style="'-hue:"> iscovery </a> </nav>
Wir beginnen mit dem Layout und machen unsere Elemente Grid -Gegenstände. Wir legen den NAN in der Mitte, geben Links explizite Breiten, legen beide Pseudos für jeden Link in die obere Zelle (der den Link-Text-Inhalt in die untere Zelle drückt) und richten Sie den Link-Text und die Pseudos aus.
Körper, NAV, A {Anzeige: Grid; } Körper { Rand: 0; Höhe: 100VH; } nav { Grid-Auto-Flow: Säule; Ort selbst: Zentrum; Polsterung: .75em 0 .375em; } A { Breite: 5EM; Text-Align: Mitte; & :: vor, & :: nach { Gitterfläche: 1/1; Inhalt: Attr (Data-ICO); } }
Beachten Sie, dass das Aussehen der Emojis je nach Browser, den Sie verwenden, die Demos verwenden wird.
Wir wählen eine lesbare Schriftart, stöbern ihre Größe, machen die Symbole noch größer, setzen Hintergründe und eine schönere Farbe für jede der Links (basierend auf der benutzerdefinierten Eigenschaft -Hue im Stilattribut jedes):
Körper { / * wie früher */ Hintergrund: #333; } nav { / * wie früher */ Hintergrund: #fff; Schriftart: Clamp (.625EM, 5VW, 1,25EM)/ 1,25 Ubuntu, Sans-Serif; } A { / * wie früher */ Farbe: HSL (var (-Hue), 100%, 50%); Textdekoration: Keine; & :: vor, & :: nach { / * wie früher */ Schriftgröße: 2.5EM; } }
Hier werden die Dinge interessant, weil wir zwischen den beiden Emoji -Ebenen unterscheiden, die mit den Link -Pseudos erstellt wurden. Wir bewegen uns leicht und drehen das :: vor Pseudo, machen es mit einem Sepia (1) -Filter monochrom, bringen Sie es auf den rechten Farbton und stöbern Sie in den Kontrast () - eine alte, aber Goldie -Technik von Lea Verou. Wir wenden auch einen Filter an: Graustufen (1) auf das :: nach pseudo und machen es semitransparent, weil wir sonst nicht in der Lage wären, den anderen Pseudo durch ihn zu sehen.
A { / * wie früher */ & :: vor { verwandeln: translate (.375em, -.25em) drehen (22,5 Grad); Filter: Sepia (1) Hue-rotate (calc (var (-hue)-50 Grad)) gesättigt (3); } &::nach { Deckkraft: .5; Filter: Graustufen (1); } }
So weit, so gut ... na und? Der nächste Schritt, den ich dumm dachte, wäre der letzte, wenn ich die Idee hatte, dies zu codieren, beinhaltet das Einstellen eines Hintergrunds-Filters: Blur (5PX) auf der oberen (:: After) -Schiete.
Beachten Sie, dass Firefox noch die GFX.Webrender.All und layout.css.backdrop-filter.Enabled Flags benötigen.
Leider sieht das Ergebnis nicht so aus, was ich erwartet hatte. Wir erhalten eine Art Überlagerung der Größe des gesamten oberen Symbols, aber das untere Symbol ist nicht wirklich verschwommen.
Ich bin mir jedoch ziemlich sicher, dass ich zuvor mit Backdrop-Filter: Blur () gespielt habe und es hat funktioniert. Was zum Teufel ist hier zu haarig?
Nun, wenn Sie überhaupt keine Ahnung haben, warum etwas nicht funktioniert, können Sie nur ein weiteres funktionierendes Beispiel nehmen, es anzupassen, um zu versuchen, das gewünschte Ergebnis zu erzielen ... und zu sehen, wo es bricht!
Sehen wir uns also eine vereinfachte Version meiner älteren funktionierenden Demo an. Die HTML ist nur ein Artikel in einem Abschnitt. Im CSS haben wir zunächst einige Dimensionen festgelegt, dann einen Bildhintergrund in den Abschnitt und einen halbtransparenten im Artikel festgelegt. Schließlich setzen wir die Eigenschaft im Hintergrund-Filter auf dem Artikel.
Abschnitt {Hintergrund: URL (Cake.jpg) 50%/ Cover; } Artikel { Rand: 25VMin; Höhe: 40 VH; Hintergrund: HSLA (0, 0%, 97%, .25); Backdrop-Filter: Blur (5px); }
Das funktioniert, aber wir wollen nicht, dass unsere beiden Schichten ineinander verschachtelt sind. Wir möchten, dass sie Geschwister sind. Lassen Sie uns also beide Schichtartikel -Geschwister erstellen, sie teilweise überlappen und prüfen, ob unser Glasmorphismus -Effekt noch funktioniert.
<article class="'base'"> </article> <article class="'Gray'"> </article>
Artikel {Breite: 66%; Höhe: 40 VH; } .Base {Hintergrund: URL (Cake.jpg) 50%/ Cover; } .grau { Marge: -50% 0 0 33%; Hintergrund: HSLA (0, 0%, 97%, .25); Backdrop-Filter: Blur (5px); }
In Chrome scheint immer noch alles in Ordnung zu sein und zum größten Teil auch Firefox. Es ist nur so, wie Blur () an den Rändern in Firefox umständlich und nicht so aussieht, was wir wollen. Und basierend auf den wenigen Bildern der Spezifikation glaube ich, dass das Firefox -Ergebnis auch falsch ist?
Ich nehme an, eine Fix für das Firefox-Problem in dem Fall, in dem unsere beiden Schichten auf einem festen Hintergrund (in diesem speziellen Fall weiß) sitzen, besteht darin, die untere Schicht (.base) einen Box-Shadow ohne Offsets, ohne Unschärfe und einen auf der oberen Schicht angewendeten Spread-Radius zu geben, der doppelt so hoch ist. Sicher genug, diese Korrektur scheint in unserem speziellen Fall zu funktionieren.
Die Dinge werden viel haariger, wenn unsere beiden Schichten auf einem Element mit einem Bildhintergrund sitzen, der nicht behoben ist (in diesem Fall könnten wir einen Ansatz von Layered -Hintergründen verwenden, um das Problem der Firefox zu lösen), aber das ist hier nicht der Fall, daher werden wir uns nicht damit einlassen.
Gehen wir trotzdem mit dem nächsten Schritt über. Wir möchten nicht, dass unsere beiden Schichten zwei Quadratkästen sind. Wir möchten dann Emojis, was bedeutet, dass wir nicht sicherstellen können, dass die Semitransparenz für den oberen mit einem HSLA () -Gtinten Hintergrund eine Semitransparente für die obere Weise sicherstellen kann - wir müssen die Opazität verwenden.
.grau { / * wie früher */ Deckkraft: .25; Hintergrund: HSL (0, 0%, 97%); }
Es sieht so aus, als hätten wir das Problem gefunden! Aus irgendeinem Grund bricht die Top-Layer-Semitransparent mithilfe der Opazität den Hintergrund-Filter-Effekt sowohl in Chrom als auch in Firefox aus. Ist das ein Fehler? Soll das passieren?
MDN sagt Folgendes im ersten Absatz auf der Seite Backdrop-Filter:
Da es für alles hinter dem Element gilt, müssen Sie das Element oder seinen Hintergrund zumindest teilweise transparent machen.
Wenn ich den obigen Satz nicht verstehe, scheint dies darauf hinzudeuten, dass die Opazität den Effekt nicht brechen sollte, obwohl dies sowohl in Chrom als auch in Firefox der Fall ist.
Was ist mit der Spezifikation? Nun, die Spezifikation ist eine riesige Textwand ohne viele Illustrationen oder interaktive Demos, die in einer Sprache geschrieben wurden, die das Lesen so ansprechend wie das Schnüffeln eines Stinkters einsetzt. Es enthält diesen Teil, den ich ein Gefühl habe, aber ich bin mir nicht sicher, dass ich verstehe, was es zu sagen versucht-dass die Opazität, die auf dem oberen Element festgelegt ist, auf dem wir auch den Hintergrund-Filter haben, auch auf das Geschwister darunter angewendet wird? Wenn dies das beabsichtigte Ergebnis ist, geschieht es in der Praxis sicherlich nicht.
Die Wirkung des Hintergrundfilters ist nicht sichtbar, es sei denn, ein Teil des Elements B ist halbtransparent. Beachten Sie auch, dass jede an Element B angewendete Deckkraft auch auf das gefilterte Hintergrundbild angewendet wird.
Unabhängig von der Spezifikation bleibt die Tatsache bestehen: Die Top -Layer -Semitransparent mit der Eigenschaft der Opazität bricht den Glassmorphismus -Effekt sowohl in Chrom als auch in Firefox. Gibt es eine andere Möglichkeit, einen Emoji -Semitransparenten zu machen? Nun, wir könnten versuchen, Filter zu filtern: Deckkraft ()!
An diesem Punkt sollte ich wahrscheinlich berichten, ob diese alternative Funktionsweise funktioniert oder nicht, aber die Realität ist… Ich habe keine Ahnung! Ich habe ein paar Tage in diesem Schritt in der Zwischenzeit verbracht und den Test in der Zwischenzeit unzählige Male überprüfen - manchmal funktioniert er, manchmal nicht in den gleichen Browsern, mit unterschiedlichen Ergebnissen je nach Tageszeit. Ich fragte auch auf Twitter und bekam gemischte Antworten. Nur einer dieser Momente, in denen Sie sich fragen können, ob ein Halloween -Geist Ihren Code nicht verfolgt, Angst und Narben. Für die Ewigkeit!
Es sieht so aus, als ob alle Hoffnung weg ist, aber versuchen wir es nur noch eins: Ersetzen der Rechtecke durch Text, wobei der obere Semitransparent mit Farbe ist: hsla (). Wir können den coolen Emoji -Glassmorphismus -Effekt, den wir gesucht haben, möglicherweise nicht erzielen, aber vielleicht können wir ein solches Ergebnis für einfachen Text erzielen.
Daher fügen wir unseren Artikelelementen Textinhalte hinzu, löschen ihre explizite Größe, stöbern ihre Schriftgröße, passen den Rand an, der uns teilweise Überlappungen gibt und vor allem die Hintergrunddeklarationen in der letzten Arbeitsversion durch farbige Version ersetzen. Aus Gründengründen setzen wir auch Aria-Hidden = 'True' unten.
<article class="'base'" aria-hidden="'true'"> lion? </article> <artikel class="'Gray'"> Lion? </artikel>
Artikel {Schriftart: 900 21VW/ 1 Cursive; } .base {color: #ff7a18; } .grau { Rand: -.75em 0 0 .5EM; Farbe: HSLA (0, 0%, 50%, .25); Backdrop-Filter: Blur (5px); }
Hier gibt es ein paar Dinge zu beachten.
Erstens macht es Emojis -Semitransparent, nicht nur in Chrome und in Firefox, auch in einem unteruhluster Alpha die Farbeigenschaft auf einen Wert mit einem unterubstierenden Alpha zu setzen ! Dies ist etwas, das ich noch nie gewusst habe, und ich finde absolut umwerfend, da die anderen Kanäle Emojis in keiner Weise beeinflussen.
Zweitens verwischen sowohl Chrome als auch Firefox den gesamten Bereich des orangefarbenen Textes und Emoji, der unter dem Begrenzungsfeld der oberen halbransparenten grauen Schicht gefunden wird, anstatt nur das zu verwischen, was sich unter dem tatsächlichen Text befindet. In Firefox sehen die Dinge aufgrund dieses unangenehmen scharfen Kanteneffekts noch schlechter aus.
Obwohl die Box -Unschärfe nicht das ist, was wir wollen, kann ich nicht anders, als zu glauben, dass sie sinnvoll ist, da die Spezifikation Folgendes sagt:
[…] Um ein „transparentes“ Element zu erstellen, das das vollständige filtrierte Hintergrundbild ermöglicht, können Sie „Hintergrundfarbe: transparent“ verwenden.
Lassen Sie uns also einen Test durchführen, um zu überprüfen, was passiert, wenn die oberste Ebene eine weitere nicht rektanguläre Form ist, die kein Text ist, sondern mit einem Hintergrundgradienten, einem Clip-Pfad oder einer Maske erhalten wird!
Sowohl in Chrom als auch in Firefox wird der Bereich unter der gesamten Schachtel der obersten Schicht verschwommen, wenn die Form mit Hintergrund erhalten wird: Gradient (), was, wie im Textfall erwähnt, nach der Spezifikation sinnvoll ist. Chrome respektiert jedoch die Clip-Pfad- und Maskenformen, während Firefox nicht. Und in diesem Fall weiß ich wirklich nicht, was korrekt ist, obwohl das Chromergebnis für mich sinnvoller ist.
Dieses Ergebnis und ein Twitter -Vorschlag, den ich bekam, als ich fragte, wie die Unschärfe die Textkanten respektieren kann, und nicht die des Begrenzungsfelds führte mich zum nächsten Schritt für Chrome: Auftragen einer Maske auf der oberen Ebene (.grey). Diese Lösung funktioniert aus zwei Gründen nicht in Firefox: Erste, Text ist leider ein nicht standardmäßiger Masken-Clip-Wert, der nur in Webkit-Browsern funktioniert, und um zwei, wie der obige Test gezeigt, beschränkt das Maskieren den Unschärfenbereich nicht auf die Form der Maske in Firefox.
/ * wie früher */ .grau { / * wie früher */ -Webkit-Maske: Linear-Gradient (rot, rot) Text; / * funktioniert nur in Webkit -Browsern */ }
Okay, das sieht tatsächlich so aus, was wir wollen, also können wir sagen, dass wir in die richtige Richtung gehen! Hier haben wir jedoch ein orangefarbenes Herz -Emoji für die untere Schicht und ein schwarzes Herz -Emoji für die obere halbtransparente Schicht verwendet. Andere generische Emojis haben keine Schwarz -Weiß -Versionen, daher war meine nächste Idee, die beiden Schichten zunächst identisch zu machen, dann den oberen Semitransparenten zu machen und Filter zu verwenden: Graustufe (1) darauf.
Artikel { Farbe: HSLA (25, 100%, 55%, var (-a, 1)); Schriftart: 900 21VW/ 1,25 Kursiv; } .grau { -A: .25; Rand: -1em 0 0 .5EM; Filter: Graustufen (1); Backdrop-Filter: Blur (5px); -Webkit-Maske: Linear-Gradient (rot, rot) Text; }
Nun, das hatte sicherlich den Effekt, den wir auf der obersten Schicht wollten. Leider scheint es aus irgendeinem seltsamen Grund auch den verschwommenen Bereich der darunter liegenden Schicht beeinflusst zu haben. In diesem Moment ist es in Betracht gezogen, den Laptop kurz aus dem Fenster zu werfen ... bevor Sie die Idee bekommen, eine weitere Ebene hinzuzufügen.
Es würde so laufen: Wir haben die Basisschicht, genau wie wir es bisher bisher leicht von den beiden anderen über ihr verankert haben. Die mittlere Schicht ist ein „Geist“ (transparent), der den Hintergrund-Filter angewendet hat. Und schließlich ist der obere Semitransparent und erhält den Graustufen -Filter (1).
Körper {Anzeige: Grid; } Artikel { Gitterfläche: 1/1; Ort selbst: Zentrum; Polsterung: .25em; Farbe: HSLA (25, 100%, 55%, var (-a, 1)); Schriftart: 900 21VW/ 1.25 Pacifico, Z003, Segoe Script, Comic Sans MS, Cursive; } .base {margin: -.5em 0 0 -.5em; } .midl { -A: 0; Backdrop-Filter: Blur (5px); -Webkit-Maske: Linear-Gradient (rot, rot) Text; } .Grey {Filter: Graustufen (1) Opazität (.25)}
Jetzt kommen wir irgendwo! Es gibt nur noch eine Sache zu tun: Machen Sie die Basisschicht monochrom!
/ * wie früher */ .base { Rand: -.5EM 0 0 -.5EM; Filter: Sepia (1) Hue-Rotat (165 °) Kontrast (1,5); }
Okay, das ist der Effekt, den wir wollen!
Während ich die Chromlösung codierte, konnte ich nicht anders, als zu glauben, dass wir in der Lage sein könnten, das gleiche Ergebnis von Firefox zu erzielen, da Firefox der einzige Browser ist, der die Funktion Element () unterstützt. Diese Funktion ermöglicht es uns, ein Element zu nehmen und es als Hintergrund für ein anderes Element zu verwenden.
Die Idee ist, dass die Schichten .Base und .Grey die gleichen Stile wie in der Chrome -Version haben, während die mittlere Schicht einen Hintergrund hat, der (über die Element () -Funktion) eine verschwommene Version unserer Ebenen ist.
Um die Dinge zu erleichtern, beginnen wir nur mit dieser verschwommenen Version und der mittleren Schicht.
<article id="'Blur'" aria-hidden="'true'"> lion? </article> <article class="'midl'"> lion? </article>
Wir positionieren die verschwommene Version absolut (halten sie vorerst in Sicht), machen sie monochrom und verwischen sie und verwenden sie dann als Hintergrund für .midl.
#blur { Position: absolut; Top: 2EM; Rechts: 0; Rand: -.5EM 0 0 -.5EM; Filter: Sepia (1) Hue-Rotat (165 ° C) Kontrast (1,5) Blur (5px); } .midl { -A: .5; Hintergrund: -moz -Element (#blur); }
Wir haben auch den Text im Semitransparent des .midl -Elements erstellt, damit wir den Hintergrund durch ihn sehen können. Wir werden es irgendwann voll transparent machen, aber im Moment möchten wir immer noch seine Position im Verhältnis zum Hintergrund sehen.
Wir können sofort ein Problem bemerken: Während der Margin das eigentliche #Blur -Element ausgleichen, tut es nichts, um seine Position als Hintergrund zu verschieben. Um einen solchen Effekt zu erzielen, müssen wir die Transformationseigenschaft verwenden. Dies kann uns auch helfen, wenn wir eine Rotation oder eine andere Transformation wünschen-wie sie unten zu sehen ist, wo wir den Rand durch Transformation ersetzt haben: Drehen (-9de).
Okay, aber wir bleiben vorerst nur an eine Übersetzung:
#blur { / * wie früher */ Transformation: Translate ( -. 25em, -.25em); / * ersetzt Rand *//// }
Eine Sache, die hier zu beachten ist, ist, dass ein Stück des verschwommenen Hintergrunds abgeschnitten wird, wenn es außerhalb der Grenzen der Polsterkasten der mittleren Schicht geht. Das spielt bei diesem Schritt sowieso keine Rolle, da unser nächster Zug den Hintergrund in den Textbereich übertreffen, aber es ist gut, nur diesen Platz zu haben, da die Base -Schicht genau so weit übersetzt wird.
Also werden wir die Polsterung um ein wenig erhöhen, auch wenn es zu diesem Zeitpunkt visuell keinen Unterschied macht, da wir auch Hintergrund-Clip: Text in unserem .midl-Element festlegen.
Artikel { / * wie früher */ Polsterung: .5em; } #blur { Position: absolut; unten: 100VH; Transformation: Translate ( -. 25em, -.25em); Filter: Sepia (1) Hue-Rotat (165 ° C) Kontrast (1,5) Blur (5px); } .midl { -A: .1; Hintergrund: -moz -Element (#blur); Hintergrund-Clip: Text; }
Wir haben auch das #Blur -Element außer Sichtweite bewegt und das Alpha der Farbe des .midl -Elements weiter reduziert, da wir durch den Text eine bessere Sicht auf den Hintergrund haben möchten. Wir machen es nicht vollständig transparent, halten es aber vorerst trotzdem sichtbar, damit wir wissen, welchen Bereich er abdeckt.
Der nächste Schritt besteht darin, das .base -Element mit so ziemlich den gleichen Stilen wie im Chromgehäuse hinzuzufügen und den Rand nur durch eine Transformation zu ersetzen.
<article id="'Blur'" aria-hidden="'true'"> lion? </article> <article class="'base'" aria-hidden="'true'"> lion? </article> <article class="'midl'"> lion? </article>
#blur { Position: absolut; unten: 100VH; Transformation: Translate ( -. 25em, -.25em); Filter: Sepia (1) Hue-Rotat (165 ° C) Kontrast (1,5) Blur (5px); } .base { Transformation: Translate ( -. 25em, -.25em); Filter: Sepia (1) Hue-Rotat (165 °) Kontrast (1,5); }
Da ein Teil dieser Stile üblich ist, können wir auch die .base -Klasse zu unserem verschwommenen Element #Blur hinzufügen, um die Duplikation zu vermeiden und die Menge an Code zu verringern, die wir schreiben.
<article id="'Blur'" class="'base'" aria-hidden="'true'"> lion? </article> <article class="'base'" aria-hidden="'true'"> lion? </article> <article class="'midl'"> lion? </article>
#blur { --R: 5px; Position: absolut; unten: 100VH; } .base { Transformation: Translate ( -. 25em, -.25em); Filter: Sepia (1) Hue-Rotat (165de) Kontrast (1,5) Blur (var (-r, 0)); }
Wir haben hier ein anderes Problem. Da die .Base -Schicht eine Transformation aufweist, liegt sie jetzt trotz der DOM -Reihenfolge auf der .midl -Schicht. Die einfachste Lösung? Fügen Sie Z-Index: 2 auf das .midl-Element hinzu!
Wir haben immer noch ein weiteres, etwas subtileres Problem: Das Base -Element ist immer noch unter den semitransparenten Teilen des verschwommenen Hintergrunds sichtbar, den wir auf dem .midl -Element festgelegt haben. Wir möchten nicht, dass die scharfen Kanten des. Base -Layer -Textes darunter sind, aber wir sind, weil verschwommene Pixel nahe am Rand semitransparent werden.
Abhängig von der Art von Hintergrund, die wir über die Eltern unserer Textschichten haben, ist dies ein Problem, das mit ein wenig oder viel Anstrengung gelöst werden kann.
Wenn wir nur einen soliden Hintergrund haben, wird das Problem gelöst, indem die Hintergrundfarbe in unserem .midl-Element auf denselben Wert festgelegt wird. Glücklicherweise ist dies unser Fall, sodass wir nicht über das andere Szenario diskutieren werden. Vielleicht in einem anderen Artikel.
.midl { / * wie früher */ Hintergrund: -moz -Element (#blur) #fff; Hintergrund-Clip: Text; }
Wir nähern uns einem schönen Ergebnis von Firefox! Alles, was zu tun bleibt, ist die obere .Grey -Ebene mit genau den gleichen Stilen wie in der Chrome -Version hinzuzufügen!
.Grey {Filter: Graustufen (1) Opazität (.25); }
Leider erzeugt dies nicht das gewünschte Ergebnis, was wirklich offensichtlich ist, wenn wir auch den Text mit mittlerer Ebene vollständig transparent machen (indem wir sein Alpha -A: 0), so dass wir nur den Hintergrund sehen (der das verschwommene Element #blur über festes Weiß verwendet), das in den Textbereich abgeschnitten ist:
Das Problem ist, dass wir die .Grey -Schicht nicht sehen können! Aufgrund der Einstellung von Z-Index: 2 darauf befindet sich die mittlere Schicht .Midl jetzt über der oberen Schicht (die .grey One) trotz der DOM-Reihenfolge. Das Fix? Setzen Sie Z-Index: 3 auf der .grey-Schicht!
.grau { Z-Index: 3; Filter: Graustufen (1) Deckkraft (.25); }
Ich gebe nicht wirklich gern Z-Index-Schicht für Layer, aber hey, es ist niedrig und es funktioniert! Wir haben jetzt eine schöne Firefox -Lösung:
Wir beginnen mit dem Firefox -Code, weil es nur noch mehr davon gibt:
<article id="'Blur'" class="'base'" aria-hidden="'true'"> lion? </article> <article class="'base'" aria-hidden="'true'"> lion? </article> <article class="'midl'" aria-hidden="'true'"> lion? </article> <artikel class="'Gray'"> Lion? </artikel>
Körper {Anzeige: Grid; } Artikel { Gitterfläche: 1/1; Ort selbst: Zentrum; Polsterung: .5em; Farbe: HSLA (25, 100%, 55%, var (-a, 1)); Schriftart: 900 21VW/ 1,25 Kursiv; } #blur { --R: 5px; Position: absolut; unten: 100VH; } .base { Transformation: Translate ( -. 25em, -.25em); Filter: Sepia (1) Hue-Rotat (165de) Kontrast (1,5) Blur (var (-r, 0)); } .midl { -A: 0; Z-Index: 2; Hintergrund: -moz -Element (#blur) #fff; Hintergrund-Clip: Text; } .grau { Z-Index: 3; Filter: Graustufen (1) Deckkraft (.25); }
Die zusätzlichen Z-Index-Deklarationen beeinflussen das Ergebnis nicht in Chrom, und das außer Sicht #Blur-Element auch nicht. Die einzigen Dinge, die dies fehlt, damit dies in Chrome funktioniert, sind die Hintergrundfilter- und Maskenerklärungen auf dem .midl-Element:
Backdrop-Filter: Blur (5px); -Webkit-Maske: Linear-Gradient (rot, rot) Text;
Da wir nicht möchten, dass der Hintergrund-Filter in Firefox angewendet wird und wir auch nicht möchten, dass der Hintergrund in Chrome angewendet wird, verwenden wir @Supports:
$ r: 5px; / * wie früher */ #blur { / * wie früher */ --R: #{$ r}; } .midl { -A: 0; Z-Index: 2; / * muss in @Supports zurückgesetzt werden, damit es nicht in Firefox angewendet wird */ Backdrop-Filter: Blur ($ R); / * Ungültiger Wert in Firefox, sowieso nicht angewendet, kein Zurücksetzen */ -Webkit-Maske: Linear-Gradient (rot, rot) Text; @Supports (Hintergrund: -moz -Element (#blur)) { / * für Firefox * / Hintergrund: -moz -Element (#blur) #fff; Hintergrund-Clip: Text; Backdrop-Filter: Keine; } }
Dies gibt uns eine Cross-Browser-Lösung!
Während das Ergebnis in den beiden Browsern nicht dasselbe ist, ist es immer noch ziemlich ähnlich und gut genug für mich.
Leider ist das unmöglich.
Zunächst einmal erfordert die Firefox -Lösung, dass wir mindestens zwei Elemente haben, da wir eine (auf die durch ihre ID verwiesen) als Hintergrund für einen anderen verwendet werden.
Zweitens ist der erste Gedanke mit den verbleibenden drei Schichten (die die einzigen für die Chromlösung sowieso benötigen), dass einer von ihnen das tatsächliche Element und die beiden anderen Pseudos sein könnte, aber in diesem speziellen Fall nicht so einfach.
Für die Chromlösung hat jede der Schichten mindestens eine Eigenschaft, die auch irreversibel auf Kinder und Pseudos auswirkt, die sie möglicherweise haben kann. Für die .Base- und .grey -Schichten ist das die Filtereigenschaft. Für die mittlere Schicht ist das die Maskeneigenschaft.
Obwohl es nicht hübsch ist, all diese Elemente zu haben, sieht es so aus, als hätten wir keine bessere Lösung, wenn wir möchten, dass der Glassmorphismus -Effekt auch an Emojis arbeitet.
Wenn wir nur den Glassmorphismus -Effekt auf einfachen Text - keine Emojis auf dem Bild - wollen, kann dies mit nur zwei Elementen erreicht werden, aus denen nur einer für die Chromlösung benötigt wird. Das andere ist das #Blur -Element, das wir nur in Firefox benötigen.
<article id="'Blur'"> Blood </article> <article class="'text'" aria-hidden="'true'" data-text="'blood'"> </article>
Wir verwenden die beiden Pseudos des .textelements, um die Basisschicht (mit dem :: vor) und eine Kombination der beiden anderen Schichten (mit dem :: nach) zu erstellen. Was uns hier hilft, ist, dass wir mit Emojis aus dem Bild keinen Filter benötigen: Graustufen (1), sondern die Sättigungskomponente des Farbwerts steuern können.
Diese beiden Pseudos sind übereinander gestapelt, wobei der untere (:: vor) durch die gleiche Menge und die gleiche Farbe wie das #Blur -Element aufweist. Dieser Farbwert hängt von einer Flagge ab -F -F, die uns hilft, sowohl die Sättigung als auch die Alpha zu steuern. Für das #Blur-Element und das :: vor Pseudo (--f: 1) beträgt die Sättigung 100% und das Alpha 1. Für das :: nach Pseudo (--f: 0) beträgt die Sättigung 0% und das Alpha 0,25.
$ r: 5px; %Text {// verwendet von #Blur und beiden .Text Pseudos --f: 1; Gitterfläche: 1/1; // Pseudos stapeln, ignoriert für absolut positionierte #Base Polsterung: .5em; Farbe: HSLA (345, Calc (var (-f)*100%), 55%, Calc (.25,75*var (-f)); Inhalt: Attr (Datentext); } Artikel {Schriftart: 900 21VW/ 1.25 Cursive} #blur { Position: absolut; unten: 100VH; Filter: Blur ($ R); } #blur, .Text :: vor { Transformation: Translate ( -. 125em, -.125em); @extend %text; } .Text { Anzeige: Grid; &::nach { --f: 0; @extend %text; Z-Index: 2; Backdrop-Filter: Blur ($ R); -Webkit-Maske: Linear-Gradient (rot, rot) Text; @Supports (Hintergrund: -moz -Element (#blur)) { Hintergrund: -moz -Element (#blur) #fff; Hintergrund-Clip: Text; Backdrop-Filter: Keine; } } }
Die gute Nachricht hier ist unser spezieller Anwendungsfall, in dem wir nur den GlaSmorphismus -Effekt auf das Link -Symbol (nicht auf dem gesamten Link einschließlich des Textes) haben, vereinfacht die Dinge tatsächlich ein kleines bisschen.
Wir verwenden den folgenden Mops, um die Struktur zu erzeugen:
- sei data = { - Home: {ICO: '?', Hue: 200}, - Hinweise: {ICO: '? umpf', Hue: 260}, - Aktivität: {ICO: '?', Hue: 320}, - Entdeckung: {ICO: '?', Hue: 30} -}; - sei E = Object.Entries (Daten); - Sei n = E.Length; Navigation - für (lass i = 0; i <n i ico="E" .ico a.item style="`--hue:" .hue deg span.icon.tint aria-hidden="'true')" span.icon.midl span.icon.grey><p> Dies erzeugt eine HTML -Struktur wie die folgende:</p> <pre rel="HTML" data-line=""> <nav> <a class="'item'" item> <span class="'icon" tint id="'Blur0'" aria-hidden="'true'">? </span> <span class="'icon" tint aria-hidden="'true'">? </span> <span class="'icon" midl aria-hidden="'true'" style="'Hintergrund-Image:">? </span> <span class="'icon" grau aria-hidden="'true'">? </span> heim </a> </nav>
Wir könnten wahrscheinlich einen Teil dieser Spannweiten durch Pseudos ersetzen, aber ich denke, es ist konsequenter und einfacher wie dieses, also ist es ein Spannwichsandwich!
Eine sehr wichtige Sache ist zu bemerken, dass wir für jedes der Elemente eine andere verschwommene Symbolschicht haben (da jedes Element ein eigenes Symbol hat). Daher setzen wir den Hintergrund des .midl -Elements in dem Style -Attribut. Wenn wir auf diese Weise Dinge tun, können wir nicht Änderungen an der CSS -Datei vornehmen, wenn wir Einträge aus dem Datenobjekt hinzufügen oder entfernen (somit die Anzahl der Menüelemente ändern).
Wir haben fast das gleiche Layout und die gleichen Layout- und Feinstile, die wir hatten, als wir zum ersten Mal CSS in der Navigationsleiste haben. Der einzige Unterschied besteht darin, dass wir jetzt keine Pseudos in der oberen Zelle eines Elementrasters haben. Wir haben die Spannweiten:
Span { Gitterfläche: 1/1; / * stapeln Sie alle Emojis übereinander */// Schriftgröße: 4EM; / * Bump Up Emoji Größe */ }
Für die Emoji-Ikonenschichten selbst müssen wir auch nicht viele Änderungen gegenüber der Cross-Browser-Version vornehmen, die wir etwas früher erhalten haben, obwohl es einige LTTLE-Versionen gibt.
Zunächst verwenden wir die Transformations- und Filterketten, die wir ursprünglich ausgewählt haben, als wir die Link Pseudos anstelle von Spannweiten verwendeten. Wir brauchen auch die Farbe auch nicht: HSLA () Erklärung zu den Spannweitenschichten, da wir hier nur Emojis haben, ist es nur der Alpha -Kanal, der zählt. Die Standardeinstellung, die für die .Base- und die .Grey -Schichten erhalten bleiben, beträgt 1., anstatt einen Farbwert festzulegen, bei dem nur das Alpha, -ein Kanal von Bedeutung, und wir ändern diese auf 0 auf der .midl -Ebene, wir setzen direkt Farbe: transparent dort. Wir müssen auch nur die Hintergrundfarbe auf das .midl-Element im Firefox-Fall einstellen, da wir das Hintergrundbild bereits im Style-Attribut festgelegt haben. Dies führt zur folgenden Anpassung der Lösung:
.base { / * mono emoji Version * / Transformation: Translate (.375EM, -.25EM) Drehung (22,5 Grad); Filter: Sepia (1) Hue-Rotat (var (-hue)) sättig (3) Blur (var (-r, 0)); } .Midl { / * Mitte, transparente Emoji -Version * / Farbe: transparent; / * Also ist es nicht sichtbar */ Backdrop-Filter: Blur (5px); -Webkit-Maske: Linear-Gradient (rot 0 0) Text; @Supports (Hintergrund: -moz -Element (#B)) { Hintergrundfarbe: #fff; Hintergrund-Clip: Text; Backdrop-Filter: Keine; } }
Und das war's - wir haben einen schönen Icon -Glasmorphismus -Effekt für diese Navigationsriegel!
Es gibt nur noch eine Sache, um die man sich kümmern muss - wir wollen diesen Effekt nicht immer; Nur zu: schweben oder: Fokuszustände. Wir werden also eine Flagge, - -HL, die 0 im normalen Zustand ist, und 1 im: schwebenden oder: Fokuszustand, um die Opazität und Transformationswerte der .base -Spans zu kontrollieren. Dies ist eine Technik, die ich in einem früheren Artikel beschrieben habe.
$ t: .3s; A { / * wie früher */ --hl: 0; Farbe: HSL (var (-hue), calc (var (-hl)*100%), 65%); Übergang: Farbe $ T; &: Hover, &: Fokus { - -hl: 1; } } .base { verwandeln: Translate (calc (var (-hl)*. 375em), calc (var (-hl)*-. 25em)) rotieren (calc (var (-hl)*22,5 Grad)); Opazität: var (-hl); Übergang: $ T, Opazität $ T; }
Das Ergebnis ist in der folgenden interaktiven Demo zu sehen, wenn die Symbole schwebten oder fokussiert sind.
Ich habe mir diese Frage natürlich gestellt, nachdem ich die CSS Emoji -Version zum Laufen gebracht hatte. Wäre der einfache SVG -Weg nicht sinnvoller als ein Spannweinweinwich, und wäre es nicht einfacher? Nun, obwohl es sinnvoller ist, zumal wir für alles keine Emojis haben, ist es leider nicht weniger Code und es ist auch nicht einfacher.
Aber wir werden in einem anderen Artikel auf Details eingehen!
Das obige ist der detaillierte Inhalt vonIconglasmorphismus -Effekt in CSS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!