Apples Liquid Glass ist der Effekt, den 2025 plötzlich jeder im Web haben wollte. Halbtransparente Bars und Buttons, die den Hintergrund nicht nur verwischen, sondern ihn an den Rändern brechen wie echtes Glas. Es sieht teuer aus, und der Reflex ist verständlich: kurz nachbauen, fertig.
Ich habe genau das getan und dabei jede Falle mitgenommen, die es gibt. Dieser Beitrag ist die Anleitung, die ich mir vorher gewünscht hätte, erst die Physik, dann der lauffähige Code, dann die Eigenheiten, die in keinem der glänzenden Tutorials stehen. Und am Ende die Frage, ob man das auf einer echten Kundenseite überhaupt will.
Eine Sache vorweg. Ein Teil dieses Artikels stand hier ein paar Wochen lang falsch. Ich hatte einen Fix beschrieben, der in jeder Demo funktioniert und trotzdem keine Brechung erzeugt. Was dabei wirklich passiert, steht weiter unten unter Punkt 1.
Refraktion, nicht Blur: warum Liquid Glass anders ist
Der klassische Glassmorphism-Look ist schnell erklärt: eine halbtransparente Fläche, dahinter ein backdrop-filter: blur(). Das Licht des Hintergrunds wird gestreut, alles wird milchig. Frosted Glass eben.
Liquid Glass macht etwas anderes. Echtes Glas streut Licht nicht nur, es bricht es. An einer gekrümmten Kante ändert der Lichtstrahl seine Richtung, der Hintergrund erscheint dort verschoben und verzerrt. Physikalisch beschreibt das das Snellsche Gesetz: Der Winkel, in dem ein Strahl gebrochen wird, hängt vom Brechungsindex und von der Neigung der Oberfläche ab. In der Mitte einer flachen Glasscheibe passiert fast nichts, an der gekrümmten Randzone dagegen viel.
Genau das ist der Kern von Liquid Glass, und es sind vier Eigenschaften, die es von simplem Blur trennen:
- Refraktion an den Rändern. Der Hintergrund wird an den Kanten gebogen, die Mitte bleibt klar.
- Eine helle Glanzkante (Specular Highlight) am Rand - der sichtbarste Unterschied zu reinem Blur.
- Tiefe durch Schatten und eine leichte Innenbeleuchtung.
- Optional chromatische Aberration, feine Farbsäume an der Kante, wie bei einer echten Linse.
Wer nur blur() einsetzt, bekommt Frosted Glass. Für die Brechung braucht es mehr: eine SVG-Displacement-Map.
Der Teil, der überall funktioniert: das CSS-Gerüst
Bevor die Brechung ins Spiel kommt, steht das Gerüst - und das läuft in jedem modernen Browser. Ein großer Eckenradius, ein zurückhaltender Blur mit erhöhter Sättigung (sonst wird das Glas grau statt lebendig), eine feine helle Kante als Glanz und ein Schatten für die Tiefe.
.liquid-glass {
position: relative;
isolation: isolate;
border-radius: 28px; /* großer Radius ist Pflicht */
background: rgba(255, 255, 255, 0.06);
-webkit-backdrop-filter: blur(2px) saturate(180%) brightness(1.08);
backdrop-filter: blur(2px) saturate(180%) brightness(1.08);
border: 1px solid rgba(255, 255, 255, 0.28);
box-shadow:
inset 1px 1px 1px rgba(255, 255, 255, 0.6), /* obere Glanzkante */
inset -1px -1px 1px rgba(255, 255, 255, 0.15),
0 18px 50px rgba(0, 0, 0, 0.4); /* Tiefe */
}
Das saturate(180%) ist wichtiger, als es aussieht: Ohne die Sättigungsanhebung wirkt jedes Backdrop-Glas stumpf und gräulich. Damit steht schon ein solides Frosted Glass. Für den echten Liquid-Effekt fehlt jetzt die Brechung.
Die Brechung: SVG-Displacement-Map
feDisplacementMap ist ein SVG-Filter, der jeden Pixel des Hintergrunds verschiebt - und zwar so weit, wie es ihm eine zweite Grafik vorgibt, die Displacement-Map. In dieser Map steckt die Verschiebung in den Farbkanälen: Der Rot-Wert steuert die horizontale, der Grün-Wert die vertikale Verschiebung. Ein neutrales Grau (128, 128) bedeutet keine Verschiebung, Abweichungen davon schieben den Hintergrund in eine Richtung.
Für Liquid Glass will man eine Map, die genau das nachbildet, was echtes Glas tut: in der Mitte flach (neutrales Grau, keine Brechung), an den Rändern eine Verschiebung nach außen. Erzeugt man diese Map aus der Signed Distance Function eines abgerundeten Rechtecks und nimmt deren Gradient als Oberflächen-Normale, bekommt man exakt das Bezel-Profil einer Glaskante.

So sieht diese Map aus: grau in der Mitte, an den Rändern rot nach rechts, cyan nach links, blau nach oben, grün nach unten. Genau dieses Muster erzeugt die 360-Grad-Brechung an der Kante. Eingebunden wird sie über feImage, angesteuert per backdrop-filter:
<svg width="0" height="0" aria-hidden="true" style="position:absolute">
<filter id="lg" x="-0.25" y="-0.25" width="1.5" height="1.5"
primitiveUnits="objectBoundingBox"
color-interpolation-filters="sRGB">
<feImage href="data:image/png;base64,..." preserveAspectRatio="none"
x="0" y="0" width="1" height="1" result="map"/>
<feDisplacementMap in="SourceGraphic" in2="map" scale="0.15"
xChannelSelector="R" yChannelSelector="G"/>
</filter>
</svg>
@supports (backdrop-filter: url(#lg)) {
.liquid-glass {
backdrop-filter: url(#lg) blur(2px) saturate(180%) brightness(1.08);
}
}
Das @supports ist kein Schmuck: Es sorgt dafür, dass nur Browser, die den SVG-Filter im Backdrop können, die Brechung bekommen - alle anderen bleiben beim sauberen Frost aus dem CSS-Gerüst.
Wer keine Map generieren will, kommt mit feTurbulence als Displacement-Quelle zu einem schnellen, organischen Verzerrungs-Look. Der sieht eher wässrig als glasig aus, ist aber ein Einzeiler und ein guter Startpunkt. Der saubere Kanten-Look kommt erst mit der Bezel-Map.
Die Stolperfallen, die kein Tutorial nennt
Hier wird es interessant, denn genau an diesen Stellen bin ich hängengeblieben - und die glänzenden Demo-Videos schweigen dazu.
1. Die Map mit Alpha 0 sieht richtig aus und ist trotzdem tot
Der teuerste Fehler, und ich habe ihn selbst monatelang in dieser Anleitung stehen gehabt. Bindet man die Map per feImage ein, kann Chromium die Bilddatei zusätzlich als sichtbaren Layer über das Element malen, statt sie nur als Verschiebungsquelle zu behandeln. Der naheliegende Ausweg dagegen ist, die Map mit einem Alpha-Kanal von 0 zu exportieren. feDisplacementMap liest ja nur Rot und Grün, für die Sichtbarkeit zählt Alpha, also müsste beides zusammen aufgehen.

Tut es nicht. Chromiums Grafikbibliothek multipliziert beim Dekodieren eines PNG die Farbkanäle mit dem Alpha-Wert. Bei Alpha 0 bleiben in Rot, Grün und Blau überall Nullen übrig, egal was in der Datei steht. Der Filter liest also eine Map aus lauter Nullen und verschiebt damit den gesamten Hintergrund um einen konstanten Betrag schräg nach oben links. Mit etwas Unschärfe darüber sieht das täuschend nach Brechung aus. Es ist aber nur ein Versatz, und an einer Kante rutscht der Inhalt dann sichtbar unverzerrt vorbei.
Aufgefallen ist mir das erst über eine Messung: Ich habe ein Lineal aus farbigen Streifen hinter das Glas gelegt und in Pixelschritten Screenshots gemacht, um zu sehen, welcher Streifen wo landet. Bei einer echten Linse müssen sich die Streifen an der Kante stauchen und umklappen. Sie taten es nicht, sie wanderten alle gleich weit.
Der richtige Weg ist Alpha 255 plus ein expliziter Filter-Graph, dessen letzter Schritt die Map nicht ausgibt. Die Map bleibt ein benanntes Zwischenergebnis und wird nur als in2 verwendet, sichtbar wird am Ende ausschließlich das Displacement-Ergebnis.
<filter id="lg-1" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"
x="-40" y="-40" width="680" height="130">
<feImage href="data:image/png;base64,..." result="map"
x="0" y="0" width="600" height="50" preserveAspectRatio="none"/>
<feDisplacementMap in="SourceGraphic" in2="map" result="disp"
scale="50" xChannelSelector="R" yChannelSelector="G"/>
<feMerge><feMergeNode in="disp"/></feMerge>
</filter>
2. Der Hintergrund endet an der Elementkante
Die zweite Eigenheit erklärt, warum die Brechung oben und unten oft völlig verschieden aussieht. Chromium schneidet das Backdrop exakt auf die Fläche des Elements zu. Was daneben liegt, bekommt der Filter nie zu sehen, egal wie weit man abtastet. Alles jenseits der Kante wird an der Kante gespiegelt zurückgeholt.
Das klingt nach einer Einschränkung und ist in Wahrheit der Schlüssel zum Effekt. Wer bewusst über die Kante hinaus abtastet, bekommt den Inhalt von innen gespiegelt zurück, und genau das ist die Überkopf-Optik, die man von einem Wassertropfen auf einer Scheibe kennt. Ein Profil, das nur nach innen zieht, kann diese Optik gar nicht erzeugen.
3. Filter-Definitionen werden am Namen gecacht
Der Grund, warum ich eine Weile Werte gesucht habe, die längst richtig waren. Ersetzt man das <filter>-Element unter derselben ID durch eine neue Definition, rendert der backdrop-filter munter mit der alten weiter. Bei statischem CSS fällt das nie auf, bei dynamisch erzeugten Maps sofort. Seitdem bekommt bei mir jeder Rebuild eine frische ID, und der backdrop-filter-Wert wird mitgezogen.
4. Die Brechung wirkt nur unten und rechts
Ein zweiter Klassiker: Der Effekt greift nur an der rechten und unteren Kante, oben und links passiert nichts. Ursache sind Prozent-Maße an der feImage (x="0%" width="100%"), mit denen Chromium die Map falsch auf das Element mappt. Die Lösung ist, entweder in objectBoundingBox-Einheiten zu arbeiten (ein Filter für alle Elementgrößen) oder die Map in absoluten Pixeln passend zur Elementgröße zu setzen. Verifizieren sollte man das immer über einem feinen Gitter mit einem großen Element - bei kleinen Testflächen fällt die Asymmetrie kaum auf.
5. transform verzerrt die Brechung
Sobald ein Element mit Backdrop-Refraktion per transform: scale() oder rotate() animiert wird, verzerrt sich der Koordinatenraum des Filters und die Brechung wird schief. Reines translate ist sicher. Form-Animationen wie das typische “Wobbeln” von Liquid Glass laufen deshalb besser über border-radius-Morphing als über scale.
6. iOS und Safari brechen gar nicht
Der Punkt, der einen ganzen Ansatz kippen kann: Safari und iOS unterstützen SVG-Filter als backdrop-filter schlicht nicht, aus GPU-Stabilitätsgründen. Es gibt keinen Weg, echte Backdrop-Refraktion auf dem iPhone zu erzwingen - Apples eigenes Glas ist nativ in Metal gebaut, nicht im offenen Web verfügbar. Wer die Brechung dort trotzdem will, muss den Hintergrund duplizieren und filter statt backdrop-filter auf die Kopie legen, was bei bewegten Hintergründen auf Mobilgeräten praktisch nicht tragbar ist. Der pragmatische Weg: iOS bekommt den Frost-Fallback, sauber getunt mit etwas mehr Sättigung und Deckkraft, und Chromium bekommt die echte Brechung. Das @supports von oben erledigt genau diese Trennung.
Warum eine gerade Rampe falsch aussieht
Wenn die Technik läuft, kommt die eigentliche Arbeit: das Profil. Also die Frage, wie weit ein Pixel je nach Abstand von der Kante verschoben wird. Die naheliegende Lösung ist eine lineare Rampe, außen viel, zur Mitte hin weniger. Das Ergebnis wirkt wie eine schräg verschobene Kopie und nicht wie Glas.
Der Grund ist Physik. Eine echte Linse dehnt nicht gleichmäßig. Zur Faltkante hin wird die Streckung immer stärker, bis das Bild dort umklappt und für einen schmalen Bereich doppelt erscheint. Das ist dieselbe Kaustik, die man in einem Wassertropfen sieht. Eine lineare Rampe hat dagegen überall dieselbe Streckung, und genau das nimmt ihr die Glaswirkung.
Sauberer wird es, wenn man nicht die Verschiebung beschreibt, sondern die Quellposition als weiche Kurve mit zwei Zonen. Außen liest sie hinter die Kante, was dank der Spiegelung aus Punkt 2 das gespiegelte Band ergibt. Am Umklapp-Punkt ist die Streckung am größten. Danach läuft sie sanft aus, bis in der Mitte wieder eins zu eins gilt. Wichtig ist, dass die Kurve dabei streng monoton bleibt, sonst gibt es Tiefen, die von keiner Bildzeile mehr angezeigt werden, und Inhalt verschwindet beim Durchscrollen in einer toten Zone.
Wie sich diese Kurve auf den Effekt auswirkt, kann man schlecht beschreiben und gut ausprobieren. Deshalb gibt es dazu eine eigene Seite mit Reglern: das Liquid-Glass-Labor. Dort lässt sich die Faltkante verschieben, die Streckung ändern und der Hintergrund per Regler durch das Glas ziehen.
Barrierefreiheit ist hier kein Anhängsel
Glas-Effekte kollidieren schneller mit Barrierefreiheit als fast jedes andere UI-Muster. Drei Dinge sind Pflicht:
- Kontrast nach dem Blur messen, nicht davor. Text auf Glas kann über einem ruhigen Hintergrund gut lesbar sein und über einem unruhigen unter die WCAG-Grenze von 4,5:1 kippen. Gemessen wird der Endzustand.
- prefers-reduced-transparency respektieren. Wer im System reduzierte Transparenz eingestellt hat, soll eine deckende Fläche sehen statt eines Glas-Effekts. Das sind ein paar Zeilen CSS, aber sie entscheiden über Nutzbarkeit für einen realen Teil der Besucher.
- Nicht stapeln. Glas auf Glas wird unlesbar. Eine Glas-Fläche pro Ansicht.
@media (prefers-reduced-transparency: reduce) {
.liquid-glass { background: #0f172a; backdrop-filter: none; -webkit-backdrop-filter: none; }
}
Brauchst du das überhaupt?
Der Code funktioniert, der Effekt sieht gut aus, trotzdem ist die wichtigste Frage nicht “wie”, sondern “ob”. Apple selbst gibt die Antwort ziemlich klar vor. In den eigenen Design-Richtlinien gehört Liquid Glass auf die Navigations- und Overlay-Ebene: Bars, schwebende Buttons, Sheets. Ausdrücklich nicht in den Inhalt, nicht auf Listen, Tabellen oder Textflächen. Und Transluzenz soll funktional sein, den darunterliegenden Kontext durchscheinen lassen, nicht Dekoration.
Für eine normale Firmen-Website heißt das: Als flächiger Look ist Liquid Glass fast immer die falsche Wahl. Er kostet Rechenleistung, er gefährdet die Lesbarkeit, und auf dem iPhone - also bei der Mehrheit der Besucher - rendert er ohnehin nur als schlichter Blur. Der ganze Aufwand für die Brechung ist auf genau den Geräten unsichtbar, auf denen die meisten Menschen die Seite sehen.
Wo er sich lohnt: als dezentes Detail. Eine schwebende Navigationsleiste, ein Cookie-Banner, ein einzelnes Overlay, wo das Glas den Inhalt darunter bewusst durchscheinen lässt und einen Moment Wertigkeit erzeugt. Sparsam, funktional, mit sauberem Fallback. So, wie Apple es meint.
Fazit
Liquid Glass im Web ist kein Zauber, sondern Lichtbrechung per Displacement-Map, plus eine Handvoll Eigenheiten, die zwischen dem hübschen Demo-Video und der funktionierenden Umsetzung liegen. Die Map, die bei Alpha 0 still zur Nullmatrix wird, der Hintergrund, der an der Elementkante endet, der gecachte Filter, die Asymmetrie durch falsche Maße und das komplette Fehlen auf iOS. Wer das kennt, spart sich einige frustrierende Nachmittage.
Das Tückische an diesen Fehlern ist, dass keiner davon einen Fehler wirft. Es sieht jedes Mal irgendwie glasig aus. Deshalb kommt man nur mit Messen weiter, mit einem bekannten Muster hinter dem Glas und der vorher ausgerechneten Erwartung, wo es landen müsste. Wenn du selbst damit spielen willst, ohne etwas nachzubauen, die Regler stehen im Liquid-Glass-Labor bereit.
Häufige Fragen
Was ist der Unterschied zwischen Glassmorphism und Liquid Glass?+
Glassmorphism (Frosted Glass) streut Licht: ein Weichzeichner hinter einer halbtransparenten Fläche. Liquid Glass bricht Licht: Der Hintergrund wird an den gekrümmten Rändern verschoben, als würde man durch eine echte Glaslinse schauen. Der sichtbarste Unterschied ist die helle Glanzkante am Rand und die Verzerrung des Hintergrunds direkt an der Kante, während die Mitte klar bleibt.
Funktioniert Liquid Glass in allen Browsern?+
Nein. Die echte Brechung über einen SVG-Filter im backdrop-filter läuft nur in Chromium-Browsern (Chrome, Edge, Brave). Safari und iOS unterstützen SVG-Filter als backdrop-filter nicht, aus GPU-Stabilitätsgründen. Dort greift ein Fallback auf reines blur() mit erhöhter Sättigung. Die Glanzkante und der große Eckenradius funktionieren überall.
Warum wird meine Displacement-Map als graues Bild sichtbar?+
Weil Chromium eine per feImage geladene Bilddatei in einem backdrop-filter zusätzlich als sichtbaren Layer über das Element malen kann, statt sie nur als Verschiebungsquelle zu nutzen. Der oft empfohlene Ausweg, die Map mit Alpha 0 zu exportieren, macht sie allerdings wirkungslos, weil Chromium beim Dekodieren die Farbkanäle mit dem Alpha-Wert multipliziert. Richtig ist Alpha 255 in Kombination mit einem expliziten Filter-Graph, dessen letzter Schritt die Map nicht ausgibt, etwa ein feMerge über das Displacement-Ergebnis.
Warum wirken meine Änderungen am SVG-Filter nicht?+
Chromium cacht Filter-Definitionen anhand ihrer ID. Ersetzt man das Filter-Element unter derselben ID, rendert der backdrop-filter weiter mit der alten Definition. Die Lösung ist, bei jedem Rebuild eine neue ID zu vergeben und den backdrop-filter-Wert entsprechend zu aktualisieren.
Sollte ich Liquid Glass auf meiner Website einsetzen?+
In den meisten Fällen sparsam bis gar nicht. Apple selbst beschränkt den Effekt auf die Navigations- und Overlay-Ebene und warnt davor, ihn im Inhalt zu verwenden. Auf einer normalen Firmen-Website kostet er Rechenleistung, gefährdet die Lesbarkeit und rendert auf iPhones nur als schlichter Blur. Als dezentes Detail auf einer Bar oder einem schwebenden Button kann er sich lohnen, als flächiger Look selten.
Ist Liquid Glass barrierefrei?+
Nur mit Sorgfalt. Der Kontrast von Text auf dem Glas muss NACH dem Weichzeichnen gemessen werden, nicht davor - über unruhigen Hintergründen kippt er leicht unter die WCAG-Grenze von 4,5:1. Zusätzlich müssen prefers-reduced-transparency und prefers-reduced-motion respektiert werden: Wer im System reduzierte Transparenz eingestellt hat, soll eine deckende Fläche sehen, keinen Glas-Effekt.
Du willst mehr erfahren?
In einem kostenlosen Erstgespräch besprechen wir, wie du diese Themen für dein Unternehmen nutzen kannst. Kein Verkaufsgespräch, sondern eine ehrliche Einschätzung.
Kostenloses Erstgespräch vereinbaren



