5 Punkte von GN⁺ 2025-09-09 | 2 Kommentare | Auf WhatsApp teilen
  • Einführung, wie sich der von Apple auf der WWDC 2025 vorgestellte Liquid-Glass-Effekt im Web mit CSS, SVG und physikbasierter Brechungsberechnung nachbilden lässt
  • Erklärung der Prinzipien der Lichtbrechung und des Einsatzes des Snelliusschen Gesetzes zur Darstellung einer Glasoberfläche und zur Simulation der Brechung
  • Demonstration, wie sich mit einer SVG-Displacement-Map ein für das Rendering geeignetes Verschiebungsvektorfeld erzeugen und auf echte UI-Komponenten anwenden lässt
  • In Chrome kann ein SVG-Filter als backdrop-filter genutzt werden; gezeigt werden Beispiele für verschiedene UI-Elemente (Lupe, Schalter, Player usw.)
  • Echtzeiteffekte sind möglich, es gibt jedoch Cross-Browser-Probleme und Performance-Grenzen; außerdem wird ein künftiger Open-Source-Plan erwähnt

Einführung

Apple hat den Liquid-Glass-Effekt erstmals im Juni 2025 auf der WWDC vorgestellt. Dieser Effekt lässt Interface-Elemente wie gebogenes Brechungsglas erscheinen und erzeugt so ein visuelles Erlebnis, das an echte Glasoberflächen erinnert. Dieser Artikel behandelt eine praktische Umsetzung, mit der sich in einer Web-Umgebung ein ähnlicher Effekt über CSS, SVG-Displacement-Maps und physikbasierte Brechungsberechnungen erzeugen lässt. Ziel ist keine vollständige Reproduktion, sondern ein skalierbarer Proof of Concept, der zentrale Merkmale wie Brechung und reflektierende Highlights nachbildet. Dafür wird schrittweise vom Grundprinzip ausgegangen, wie Licht beim Durchgang durch unterschiedliche Materialien gebrochen wird. Die am Ende bereitgestellte interaktive Demo funktioniert derzeit nur in Chrome korrekt.

Die Brechung verstehen

Brechung bezeichnet das Phänomen, dass Licht seine Ausbreitungsrichtung ändert, wenn es von einem Material in ein anderes übergeht. Das geschieht, weil sich die Lichtgeschwindigkeit je nach Material unterscheidet; die Beziehung zwischen Einfallswinkel und Brechungswinkel wird durch das Snelliussche Gesetz beschrieben:

  • n1 * sin(θ1) = n2 * sin(θ2)
    • n1: Brechungsindex des ersten Mediums
    • θ1: Einfallswinkel
    • n2: Brechungsindex des zweiten Mediums
    • θ2: Brechungswinkel

Was sich im interaktiven Diagramm beobachten lässt:

  • Haben beide Medien denselben Brechungsindex, läuft das Licht ohne Brechung geradeaus
  • Hat das zweite Medium einen höheren Brechungsindex, wird das Licht zur Normalen hin gebrochen
  • Hat das zweite Medium einen niedrigeren Brechungsindex, wird das Licht von der Normalen weg gebrochen; unter Umständen kann totale interne Reflexion auftreten
  • Fällt das Licht senkrecht auf die Oberfläche, läuft es unabhängig vom Brechungsindex geradeaus

Grenzen dieses Projekts

Um die Komplexität zu begrenzen und den Algorithmus zu vereinfachen, werden folgende Bedingungen gesetzt:

  • Brechungsindex des äußeren Mediums ist 1 (Luft)
  • Für das innere Glasmaterial wird 1,5 verwendet (typisches Glas)
  • Es wird nur ein Brechungsereignis berücksichtigt (Brechung am Austritt wird ignoriert)
  • Einfallendes Licht steht immer senkrecht auf der Hintergrundebene
  • Alle Objekte sind 2D-Formen, es werden nur Kreisformen verwendet (auf Rechtecke usw. erweiterbar, aber mit zusätzlicher Berechnung)
  • Zwischen Objekt und Hintergrundebene gibt es keinen Abstand
  • Unter diesen Bedingungen lassen sich alle Lichtstrahlen mit dem Snelliusschen Gesetz einfach berechnen

Eine Glasoberfläche erzeugen

Um den Liquid-Glass-Effekt umzusetzen, muss der Querschnitt des virtuellen Glases (Linse oder gebogenes Panel) als mathematische Funktion definiert werden.

Oberflächenfunktion

Die Glasoberfläche wird über eine surface function definiert und beschreibt die Dicke vom Rand bis zum flachen Inneren.

  • Eingabewert der Funktion 0: Außenkante, 1: Ende der Fase (Beginn der flachen Fläche)
  • Aus der Ableitung an jedem Punkt der Dicke wird der Normalenvektor der Oberfläche bestimmt
const height = f(distanceFromSide);
const delta = 0.001;
const y1 = f(distanceFromSide - delta);
const y2 = f(distanceFromSide + delta);
const derivative = (y2 - y1) / (2 * delta);
const normal = { x: -derivative, y: 1 };

Wichtige Typen von Oberflächenfunktionen

  • Convex Circle: y = sqrt((1 - (1 - x))^2)
    • Einfache Kreisbogenform, die nach innen hin schnell flach wird und dadurch eine deutliche Brechung am Rand erzeugt
  • Convex Squircle: y = ((1 - (1 - x))^4)^(1/4)
    • Eine von Apple bevorzugte Form, bei der der Übergang zwischen Kurve und Fläche weich ist und der Effekt auch bei Skalierung natürlich wirkt
  • Concave: y = 1 - Convex(x)
    • Konkave Form, bei der Licht über die Objektgrenze hinaus nach außen gebrochen wird, sodass Sampling außerhalb erforderlich ist
  • Lip: y = mix(Convex(x), Concave(x), Smootherstep(x))
    • Zusammengesetzte Struktur mit hervorstehender Lippe am Rand und flacher Einbuchtung in der Mitte

Schon mit diesen vier Funktionen lassen sich die Unterschiede der Brechung je nach Oberflächenform gut vergleichen.

Simulation

Für jede Oberflächenfunktion wird der Brechungspfad der Lichtstrahlen simuliert, um die tatsächlichen visuellen Unterschiede sichtbar zu machen.

  • Konvex bündelt die Lichtpfade nach innen, konkav drückt sie nach außen
  • Apples Liquid Glass bevorzugt meist konvexe Formen (mit Ausnahmen wie dem Switch)
  • Hintergrundpfeile visualisieren den Brechungsbetrag (die Verschiebung) farblich nach Magnitude
  • Bei gleichem Abstand zur linken bzw. rechten Kante entsteht dieselbe Verschiebung, was effiziente Wiederverwendung ermöglicht

Ein Verschiebungsvektorfeld erzeugen

Über die gesamte Glasoberfläche wird ein Vektorfeld aufgebaut, das für jede Position Richtung und Stärke der Lichtverschiebung beschreibt.

  • Bei Kreisformen erfolgt die Verschiebung relativ zur Kante immer in Richtung der Normalen

Verschiebungsstärke vorab berechnen

  • Da die Verschiebungsstärke für jeden Abstand zur Kante symmetrisch ist, werden die Werte radial vorab berechnet und in einem Array gespeichert
  • In 2D wird nur einmal gerechnet (127 Strahlensimulationen), danach wird das gesamte Feld durch Rotation um die z-Achse erzeugt

Vektornormalisierung

Damit die Vektoren in einer Displacement-Map verwendet werden können, erfolgt eine Normalisierung (maximaler Maßstab 1.0).

  • Ausgehend vom größten Verschiebungswert werden die restlichen Vektormagnituden entsprechend geteilt
const maximumDisplacement = Math.max(...displacementMagnitudes);
displacementVector_normalized = {
  angle: normalAtBorder,
  magnitude: magnitude / maximumDisplacement,
};

In der SVG-Displacement-Map wird beim Umrechnen in echte Pixelwerte über scale wieder mit dem maximalen Verschiebungswert multipliziert, um die ursprüngliche Größe herzustellen.

SVG-Displacement-Map

Um die Ergebnisse der mathematischen Brechungsberechnung tatsächlich im Browser-Rendering anzuwenden, wird eine SVG-Displacement-Map verwendet.

  • Jeder Kanal (RGBA, 8 Bit) von <feDisplacementMap /> kann jeweils die Verschiebung auf der X- bzw. Y-Achse übernehmen
  • Jeder Kanal hat Werte von 0 bis 255, wobei 128 neutral ist (keine Verschiebung)
  • Die Displacement-Map muss unbedingt in ein Bild umgewandelt werden
<svg colorInterpolationFilters="sRGB">
  <filter id={id}>
    <feImage
      href={displacementMapDataUrl}
      x={0}
      y={0}
      width={width}
      height={height}
      result="displacement_map"
    />
    <feDisplacementMap
      in="SourceGraphic"
      in2="displacement_map"
      scale={scale}
      xChannelSelector="R"
      yChannelSelector="G"
    />
  </filter>
</svg>

Scale

Die Werte der roten (X) und grünen (Y) Kanäle werden auf den Bereich [−1, 1] abgebildet.

  • Über das Attribut scale wird dann mit der maximalen Verschiebung in Pixeln multipliziert, um das eigentliche Rendering umzusetzen
  • Durch Animation von scale lässt sich die Intensität des Effekts steuern

Umwandlung von Vektor → Rot/Grün-Werten

  • Der Verschiebungsvektor (Winkel, Magnitude) wird in kartesische x/y-Koordinaten umgerechnet und dann mit 128 als neutralem Mittelpunkt auf 0 bis 255 abgebildet
const x = Math.cos(angle) * magnitude;
const y = Math.sin(angle) * magnitude;
const result = {
  r: 128 + x * 127,
  g: 128 + y * 127,
  b: 128,
  a: 255,
};

Das fertige Bild kann anschließend als Displacement-Map für den SVG-Filter verwendet werden.

Playground

Im interaktiven Playground lassen sich Oberflächenform, Fasenstärke, Glasdicke, Effect Scale usw. in Echtzeit ändern, sodass Brechungsfeld, Displacement-Map und endgültiges Rendering direkt erlebbar sind.

Specular Highlight

Zum Schluss wird ein specular highlight hinzugefügt, also der helle Kanten-Highlight-Effekt der Glasoberfläche.

  • Apples Umsetzung arbeitet als Rim Light, bei dem die Helligkeitsintensität vom Winkel zwischen Oberflächennormale und Lichtquelle abhängt

Kombination von Brechung und Specular Highlight

Im finalen SVG-Filter werden Displacement-Map und Specular-Highlight jeweils über <feImage /> geladen und mit <feBlend /> zum Endeffekt kombiniert.

  • Über die Filterparameter lassen sich unterschiedliche visuelle Ergebnisse erzeugen

SVG-Filter als backdrop-filter verwenden

  • Um UI-Komponenten praktisch mit dem Liquid-Glass-Effekt zu versehen, ist die Chrome-Unterstützung für backdrop-filter: url(#...) nötig
  • Da die Bildgröße bei backdrop-filter nicht automatisch angepasst wird, muss eine zur Elementgröße passende Displacement-Map vorbereitet werden
.glass-panel {
  backdrop-filter: url(#liquidGlassFilterId);
}

Anwendung auf reale UI-Komponenten

Auf Basis der berechneten Brechung und der Displacement-Map werden Beispiele für den Einsatz in realistisch wirkenden UI-Komponenten umgesetzt.

  • Nur Chrome kann SVG-Filter per backdrop-filter verarbeiten
  • Die Beispiele sind keine echten Produktionskomponenten, sondern dienen dazu zu demonstrieren, wie sich der Liquid-Glass-Effekt auf unterschiedliche UIs anwenden lässt

Lupe

  • Auf beiden Seiten werden Brechung und Zoom sowie zwei Displacement-Maps verwendet
  • Schatten und Skalierungsanpassungen sorgen für einen interaktiven Effekt
  • Die Linse kann per Drag verformt werden, um den Brechungspfad zu beobachten
  • Ein weiches specular highlight kommt hinzu

Searchbox

  • Der Liquid-Glass-Effekt wird auf eine Standard-Eingabebox angewendet

Switch

  • Verwendet eine Lip-Fase, außen konvex und innen konkav
  • Nur der mittlere Slider ist vergrößert/verkleinert, während die Ränder das innere Bild brechen

Slider

  • Verwendet eine konvexe Fase; der aktuelle Wert bleibt durch das Glas sichtbar, während auf beiden Seiten Hintergrundbrechung angewendet wird

Music Player

  • Ahmt den Liquid-Glass-Panel-Stil von Apple Music nach

  • Konvexe Fase und ein dezentes specular highlight verleihen Tiefe

  • Nutzt die iTunes Search API, um Album-Art, Songtitel und weitere Informationen zu laden

  • (Bereitstellung von Songtiteln und Albuminformationen in Listenform)

Fazit

Dieser Prototyp vereinfacht Apples Liquid-Glass-Konzept zu einem Echtzeit-Brechungseffekt mit einfachen Highlights. Praktisch nutzbar ist er nur in Chromium-basierten Browsern (oder Electron); in anderen Browsern kann stattdessen eine Blur-Ebene eingesetzt werden.
Es handelt sich um eine experimentelle Implementierung, und die Neugenerierung der Displacement-Map bei jeder Änderung von Form oder Größe ist sehr ineffizient (animierbar sind nur einige Parameter wie scale des Filters).
Eine spätere Open-Source-Veröffentlichung wird geprüft; außerdem wird Interesse an Optimierung und Code-Bereinigung geäußert.

2 Kommentare

 
bobross0 2025-09-16

Das ist dem Liquid Glass, das ich im Web gesehen habe, bisher am ähnlichsten.

 
GN⁺ 2025-09-09
Hacker-News-Kommentare
  • Ich habe einmal etwas Ähnliches mit einem WebGL-Shader gebaut; der Vorteil ist, dass es in mehreren Browsern funktioniert. Ich teile hier https://real-glass.vercel.app. Der schwierige Teil war, den Brechungseffekt hinter echten HTML-Elementen korrekt nachzubilden.
    • Ich frage mich, was die Ursache für den Ghosting-/Delay-Effekt ist, der entsteht, wenn man den Glaseffekt über Text legt und bewegt.
    • Ich finde das extrem cool; es sieht sogar so aus, als wäre der Dispersionseffekt mit Farbaufspaltung an den Rändern umgesetzt.
    • Die Visuals sind toll, aber für den praktischen Einsatz ist die Reaktionsgeschwindigkeit zu langsam. Die Version des Originalposters läuft deutlich flüssiger.
    • Beeindruckend.
  • Beeindruckend ist auch, dass es selbst auf einem M4-Max MacBook Pro beim Scrollen ruckelt. Wenn so eine Technik auf die gesamte UI angewendet würde, hätte ich vor allem aus Performance-Sicht Bedenken. Wahrscheinlich funktioniert das bei Apple nur, weil sie es extrem optimiert haben.
    • Als Autor des Beitrags wollte ich die Performance-Probleme eigentlich vorher beheben, aber jemand hat es früher als erwartet auf HN gepostet. Der Hinweis ist korrekt: Im Moment ist es noch etwas langsam und braucht weitere Optimierung. Nicht nur Brechungs-/Displacement-Maps, sondern auch andere Teile wie die Visualisierung sind noch nicht optimiert.
    • Da ich die Performance in Chrome schnell verbessert habe, dürfte es inzwischen etwas besser sein. In Safari ist das SVG-Rendering aber weiterhin langsam. Weil es unerwartet gepostet wurde, gibt es noch Dinge, die ich weiter verbessern muss.
    • Auf dieser Seite scrollt es nicht flüssig. CSS nutzt die GPU in den meisten Fällen nicht gut aus. Apple scheint für UI-Verarbeitung spezielle Unterstützung direkt im Silicon ergänzt zu haben.
    • Bei mir auf dem Rechner war es genauso, und auch der Randeffekt wurde nicht korrekt angezeigt.
  • Der Inhalt war gut, aber auch Aufbau und Qualität des gesamten Artikels waren hervorragend. Das Konzept von Liquid Glass selbst bringt für die praktische UX keinen besonderen zusätzlichen Vorteil mit sich – eher könnte es der UX schaden, wenn man es übertreibt –, aber es ist eine frische und unterhaltsame Erfahrung.
  • Es wurde betont, dass es sich um eine reine Chrome-Demo handelt, und dass die letzte interaktive Demo nur in Chrome funktioniert (wegen der backdrop-filter-Beschränkungen durch SVG-Filter). In anderen Browsern kann man den Artikel trotzdem lesen oder einfache Simulationen ansehen. Darauf kam die scherzhafte Reaktion: „Schande über deine ganze Familie!“
    • Dass man so vorgeht, ist unvermeidlich. Der Zweck hier ist gerade zu zeigen, dass die betreffende Funktion nur in bestimmten Browsern unterstützt wird.
    • Lustigerweise war die Seite bei mir in Chrome langsamer und das Scrollen ruckeliger, während es in Firefox trotz nicht unterstützter Effekte eher flüssiger lief. Trotzdem war ich vom Artikel selbst sehr beeindruckt.
    • Ich hatte eine ähnliche Reaktion, aber interessanterweise sah es sogar in Firefox ziemlich gut aus.
    • Falls jemand nach der Referenz sucht: https://youtu.be/GamP4chXJ2I?t=17
  • Dass die Liquid-Glass-Designsprache ins Web kommt, war zu erwarten. Aber wenn eine Website wegen Textverzerrung meinen Akku leert, werde ich nicht lange dort bleiben. Viele haben das Ruckeln bereits erwähnt, daher lasse ich es bei diesem Hinweis.
  • Tolle Arbeit, man merkt die Mühe. Aber Liquid Glass meint eigentlich die gesamte Designsprache: dass nahe beieinanderliegende Elemente wie Metaballs verschmelzen, verschiedene Tint-/Clear-Modi existieren und Controls auf einer von den Inhalten getrennten Ebene liegen. Diese Umsetzung ist so gesehen eher ein einfacher „Glass Shader“.
    • Das Verschmelzen von Elementen lässt sich mit dem deutlich einfacheren „Goo“-Filter lösen; das ist schon lange eine bekannte Methode. Eine Referenzimplementierung: https://codepen.io/lenymo/pen/pJzWVy
  • Ich habe eine JS-Bibliothek für liquid-glass geforkt und einen Patch zur Positionskorrektur ergänzt. Das macht Spaß für Präsentationen. Quellcode: https://github.com/nkzw-tech/liquid-glass
    • Cool, mir gefällt diese Variante sogar besser.
  • In Firefox funktionieren nur einige Effekte (dafür mit besserer Performance!), aber das ist die beste Umsetzung, die ich bisher gesehen habe. Ich habe in den letzten Tagen viel dazu recherchiert, deshalb finde ich es umso beeindruckender. Am besten gefielen mir das Website-Design und die sorgfältig gestalteten interaktiven Visualisierungen. Für mich ist das auf dem Niveau von Arbeiten von Bartosz Ciechanowski und Josh Comeau. Hoffentlich wird der Quellcode veröffentlicht.
  • Ich halte es trotz der Browser-Support-Einschränkungen für einen hervorragenden Versuch. Die interaktiven Inline-Beispiele haben echten Mehrwert geboten. Irgendwann hatte ich beim Lesen das Gefühl, einen Artikel von Ciechanowski zu lesen (Referenz: https://ciechanow.ski/).
  • Ich frage mich, ob die neuen ray-traced Scrollbars und Buttons tatsächlich funktionaler sind und die Produktivität gegenüber den alten Textmodus-Turbo-Vision- oder Windows-3-Buttons wirklich steigern.