DroidGlass: Liquid Glass für jede Plattform
Liquid Glass ist Apples Material, das das Darunterliegende bricht. Am Rand wird der Hintergrund wie durch eine dicke Linse zur Mitte gezogen, ein sanfter Regenbogen erscheint am Rand, ein haarfeiner Glanzstreifen läuft entlang der Kante, und bei Berührung schwillt das Glas an, dehnt sich zum Finger hin und federt zurück. Gewöhnlicher Glassmorphismus verschwimmt den Hintergrund nur unter einem weißen Schleier, weshalb er billig und matt aussieht.
Die Hauptregel des Geschmacks: Das Glas ist transparent. Wenn man nicht lesen kann, was dahinter liegt, ist es iOS 7-Milchglas, nicht Liquid Glass. Fügen Sie Unschärfe und eine Oberfläche nur dort hinzu, wo Text auf dem Glas sitzt.
Sagen Sie dem Benutzer ehrlich, wo die Grenzen liegen. Das echte Material existiert nur auf iOS, iPadOS und macOS 26 und neuer; alles andere ist eine Nachahmung. Auf Android liefert Backdrop die vollständige Imitation (die Linse benötigt Android 13). Im Web funktioniert die Brechung nur in Chromium (Chrome, Edge, Samsung Internet, Android WebView, Electron). Safari, Firefox und jeder Browser auf iOS erhalten eine leichte Unschärfe mit denselben Highlights, Schatten und Federn, aber keine Krümmung.
Arbeitsablauf
- Plattform identifizieren.
- SwiftUI, UIKit, AppKit, WidgetKit auf iOS/macOS 26: System-API, siehe
references/apple.md. Nichts nachahmen. - Jetpack Compose oder Compose Multiplatform:
references/android-compose.md. Keine Shader von Grund auf neu schreiben, die Bibliothek verwenden. - Web, Electron, Android WebView, Capacitor, Cordova, Tauri auf Windows/Android: die Engine in
assets/, siehereferences/web.md. In WebView und Electron funktioniert Refraktion immer. - React Native, Flutter: kein Systemäquivalent. Für React Native eine WebView-Ebene oder ein natives Modul auf Backdrop vorschlagen; für Flutter
BackdropFilterals Fallback und einFragmentProgrammit den Formeln ausreferences/math-and-motion.md. Aktuelle Pakete selbst prüfen, dieses Skill listet sie nicht.
- SwiftUI, UIKit, AppKit, WidgetKit auf iOS/macOS 26: System-API, siehe
- 1 bis 3 Elemente der Steuerungsebene auswählen: Tab-Leiste, schwebender Button, obere Leiste, Sheet, Menü, Schalter- oder Schieberegler-Daumen bei Berührung. Keine Inhalte aus Glas machen.
- Ein Rezept aus der folgenden Tabelle auswählen. Keine Parameter erfinden: die Werte stammen aus Kyants Katalog und wurden auf dem Bildschirm überprüft.
- Den Hintergrund unter dem Glas prüfen. Glas ist nur über reichhaltigem Inhalt sichtbar: Fotos, Farbe, Diagramme, Text beim Scrollen. Über einer leeren weißen Seite verschwindet transparentes Glas fast: Farbe dahinter setzen, eine Abdunklungsebene hinzufügen oder das Glas dort weglassen.
- Erstellen aus der richtigen Referenz und mit eigenen Augen prüfen anhand der Checkliste am Ende. Nicht ohne Screenshots von Ruhe-, Druck- und Zieh-Zuständen übergeben.
Apples Regeln
Aus den Human Interface Guidelines, WWDC25 „Meet Liquid Glass“ und beliebten Community-Skills. Wer eine davon bricht, verrät die Fälschung sofort.
- Nur die Navigations- und Steuerungsebene, die über dem Inhalt schwebt. Listen, Zeilen, Karten und der Seitenhintergrund sind nicht aus Glas. Ausnahme: Schalter- und Schieberegler-Daumen werden bei Berührung gläsern.
- Kein Glas auf Glas. Elemente auf Glas werden durch Füllung und Deckkraft abgesetzt. Ausnahme von Backdrop: ein Schieberegler-Daumen auf einem Glas-Sheet bricht das Sheet (
exportedBackdrop): eine Linse über einer anderen, nicht zwei matte Platten. - Wenig verwenden. Nur die wichtigsten Bedienelemente.
- Das Glas ist farblos. Farbe und Helligkeit kommen vom Hintergrund: hell über hell, dunkel über dunkel, das Highlight wird vom Hintergrund getönt. Keine eigene weiße oder graue Oberfläche.
- Zwei Modi, nicht mischen. Klar (Buttons, Daumen, Lupe, eine mit einem Button gruppierte Tab-Leiste): Unschärfe 0 bis 4, keine Oberfläche. Regulär (Sheet, Dialog mit langem Text): Unschärfe 8 bis 16; eine 40 bis 60%ige Oberfläche nur hinzufügen, wenn der Text ohne sie unlesbar ist.
- Nur die primäre Aktion tönen.
- Form. Kapsel: Radius gleich der halben Höhe. Konzentrische Ecken: Innenradius gleich Behälterradius minus Abstand.
- Größer bedeutet dicker: große Elemente erhalten einen breiteren gekrümmten Rand und tiefere Brechung.
- Nie Inhalt halb unter Glas ruhen lassen.
- Flüssig in Bewegung. Beim Drücken wächst das Glas um einige Pixel und neigt sich mit Dämpfung zum Finger; ein Daumen bläht sich auf das 1,5-fache auf und dehnt sich mit Geschwindigkeit zu einem Tropfen. Alles läuft auf Federn, keine linearen Übergänge.
Rezepte (Werte aus Kyants Katalog)
| Element | Effekte | Highlight und Schatten | Berührung |
|---|---|---|---|
| Button, 48 dp Kapsel | Vibranz, Unschärfe 2, Linse(12, 24) | Standard, Standardschatten | Glühen; wächst 4 dp in der Höhe; Versatz min × tanh(0,05 × Versatz / min); dehnt sich bis zu 4 dp zum Finger hin |
| Getönter Button | gleich + Tönung | gleich | gleich |
| Button mit Oberfläche | gleich + Weiß 30% | gleich | gleich |
| Schalter-Daumen 40×24 auf einer 64×28 Spur | in Ruhe Weiß 100% und Unschärfe 8; gedrückt p: Unschärfe 8(1−p), Linse(5p, 10p, Dispersion), Weiß (1−p) | Umgebung, Breite /1,5, Alpha p; Schattenradius 4, 5%; Innerer Schattenradius 4p, Alpha p | skaliert auf 1,5; die Spur zeigt durch die Linse, verkleinert auf 0,75 |
| Schieberegler-Daumen 40×24, 6 dp Spur | wie Schalter, Linse(10p, 14p) | wie Schalter | skaliert auf 1,5; Antippen der Spur springt zum Punkt |
| Tab-Leiste 64 dp | Vibranz, Unschärfe 8, Linse(24, 24), Oberfläche #FAFAFA 40% (dunkel #121212 40%) | Standard | beim Drücken wächst das gesamte Panel um 16 dp in der Breite (Labels mit) und neigt sich bis zu 4 dp nach dem Finger |
Versteckte Zeilenkopie 56 dp (tabsBackdrop) | das gleiche Panel in der Akzentfarbe, alpha(0): Vibranz, Unschärfe 8, Linse(24p, 24p), Paneloberfläche | Standard mit Alpha p, InteractiveHighlight | Symbole und Labels ×1,2 beim Drücken (LocalLiquidBottomTabScale wird nur auf dieser Zeile gesetzt) |
| Tab-Leisten-Daumen 56 dp | in Ruhe Grau 10%; gedrückt Linse(10p, 14p, Dispersion) über dem Hintergrund und der Zeilenkopie (rememberCombinedBackdrop(backdrop, tabsBackdrop)) | Standard, Schatten und innerer Schatten 8p mit Alpha p | skaliert 78/56; im Tropfen ein „Balken unter dem Balken“: eigenes Element in Akzentfarbe, vergrößert, Nachbarn an den Rändern sichtbar |
| Dialog, Radius 48 | Helligkeit 0,2 (hell), Sättigung 1,5, Unschärfe 16 (dunkel 8), Linse(24, 48, Tiefe) | Schlicht | verdunkelt den Hintergrund #29293A 23% (dunkel #121212 56%) |
| Kachel des Kontrollzentrums | Vibranz, Linse(24, 48, Tiefe) | Standard, Winkel aus Geräteneigung, Abfall 2 | Eintritt: 48 dp Versatz und Alpha |
| Lupe 128×96 | Linse(8, 24, Tiefe, Dispersion), Hintergrund 1,5-fach vergrößert | innerer Schatten 16 | ziehen |
Federn, Gesten und die gemeinsame Mathematik hinter jeder Plattform sind in references/math-and-motion.md.
Web und Android WebView in einer Minute
Kopieren Sie die drei Dateien aus assets/ unverändert in das Projekt und konfigurieren Sie sie mit Optionen. Schreiben Sie die Engine nicht neu.
<link rel="stylesheet" href="liquid-glass.css">
<button id="buy">Kaufen</button>
<div id="wifi" aria-label="Wi-Fi"></div>
<div id="volume" style="width: 280px"></div>
<nav id="tabs" style="position: fixed; left: 16px; right: 16px; bottom: 16px"></nav>
<script src="liquid-glass.js"></script>
<script src="liquid-ui.js"></script>
<script>
LiquidUI.button(document.getElementById('buy'), { tint: '#0088FF', onClick: () => {} });
LiquidUI.toggle(document.getElementById('wifi'), { checked: true, onChange: (on) => {} });
LiquidUI.slider(document.getElementById('volume'), { value: 0.4, onInput: (v) => {}, label: 'Lautstärke' });
const tabs = LiquidUI.tabs(document.getElementById('tabs'), {
items: [{ label: 'Start', icon: '<svg>…</svg>' }, { label: 'Suche', icon: '<svg>…</svg>' }],
index: 0, onChange: (i) => {},
});
// Verschmelzung: eine Leiste und ein Button nebeneinander verschmelzen zu einem Tropfen; benachbarte dehnbare Buttons tun dies von selbst
// LiquidUI.blob([tabs.panel, fab], { blur: 3.5 }); LiquidUI.autoMerge(document.body); nach einem Bildschirmwechsel LiquidUI.sweep()
// Bloßes Glas für eigenes Markup
const g = LiquidGlass.attach(document.getElementById('panel'), { radius: 28, blur: 8, refractionHeight: 24, refractionAmount: 24, surface: 'rgb(250 250 250 / .4)' });
// g.set({ lens: 0..1, blur, surface, highlightAlpha, angle, shadowAlpha, innerShadow, press: { p, x, y }, tx, ty, sx, sy, sleep })
</script>
| Datei | Was es ist |
|---|---|
assets/liquid-glass.js | Glas-Engine: Brechungskarten, Dispersion, Highlight, Schatten, Verschmelzungsgruppen (LiquidGlass) |
assets/liquid-glass.css | Basis-Stile, Barrierefreiheits-Fallbacks, Komponenten-Stile |
assets/liquid-ui.js | Federn, Gesten und Komponenten: Button, Schalter, Schieberegler, Tabs, Lupe, Blob, autoMerge (LiquidUI) |
assets/demo.html | jede Komponente auf einer Seite; öffnen, um zu sehen, wie es richtig aussieht |
Bevor Sie etwas ändern oder in eine App einbinden, lesen Sie references/web.md: es listet die Chromium-Fakten auf, die fast jede Implementierung zerstören (Hintergrund-Wurzeln, position: fixed, touch-action, Body-Hintergründe) und alle Optionen. Wenn etwas falsch aussieht, gehen Sie zu references/troubleshooting.md; wenn etwas ruckelt, zu references/performance.md.
Fünf Dinge, die im Web nie falsch gemacht werden sollten:
- Der Hintergrund muss ein echtes Element sein. Ein Hintergrund auf
body, der auf die Wurzel übergeht, wird vonbackdrop-filternicht gesehen. - Animieren Sie niemals
opacity,filter,maskoderclip-pathauf einem Vorfahren des Glases (z. B. ein Bildschirm-Fade-In): es wird zu einer Hintergrund-Wurzel und das Glas verliert seinen Hintergrund und verdunkelt sich. Verschieben Sie Bildschirme mittransformund decken Sie sie mit einer Schleier-Ebene von oben auf. - Setzen Sie kein eigenes
transformauf ein Glaselement; schreiben Sie den Basisversatz in--lg-base. - Dehnbare Buttons benötigen
touch-action: none(Standard). Mitpan-ystiehlt der Browser den Drag und sendetpointercancel. - Deaktivieren Sie in einem Android WebView langes Drücken und Haptik:
setOnLongClickListener(v -> true)undsetHapticFeedbackEnabled(false).
Barrierefreiheit und Lesbarkeit
- Die Web-Engine beachtet
prefers-reduced-transparency: reduce(Glas aus, nahezu undurchsichtige Oberfläche; Chrome und Edge 119+, noch nicht Safari oder Firefox),prefers-contrast: more(durchgehende Oberfläche und Rand) undprefers-reduced-motion(Federn werden sofort). - Komponenten erhalten Rollen und Tastaturunterstützung: Button (Enter, Leertaste),
switch(Enter, Leertaste),slider(Pfeile),tablist(linke und rechte Pfeile). Beschriften Sie sie mitaria-labeloderaria-labelledby. - Setzen Sie auf Android
semantics { role = Role.Switch }und Labels, wie in Kyants Katalog; auf alten Android prüfen, ob dieonDrawSurface-Farbe ohne Effekte lesbar ist. - Prüfen Sie den Textkontrast über dem hellsten und unruhigsten Inhalt, der unter dem Panel landen kann: 4,5:1 für Fließtext. Bei Fehlschlag Unschärfe und eine Oberfläche hinzufügen oder den Inhalt verschieben. Ein Textschatten behebt es nicht.
Nicht tun
- Eine weiße durchscheinende Oberfläche plus
blur(10px)auf Buttons: das ist Milchglas, nicht Liquid Glass. Dichte ist nur für Tab-Leisten, Sheets und Dialoge mit Text in Ordnung. - Gläserne Inhaltskarten und ein gläserner Seitenhintergrund.
- Dispersion auf großen Panels: teuer und grell.
- Ein dicker weißer Rand anstelle eines haarfeinen Highlights.
- Dieselbe Tönung auf jedem Button.
- Lineare
transitions anstelle von Federn für Druck und Ziehen. - Animieren von
widthundheightvon Glas im Web: die Karte wird jeden Frame neu aufgebaut. Skalierung animieren. - Schwere Filter-Schritte (Unschärfe, Verschiebung, Faltung, Morphologie) unter einem Ergebnis, das mehrere Schritte liest: Chrome berechnet sie einmal pro Zweig und Handys frieren ein.
- Das Glas mit einer eigenen Oberfläche „fürs Aussehen“ bemalen. Nur dichte Panels mit Text erhalten eine Oberfläche.
- Eigene Compose-Shader schreiben, wenn Backdrop passt.
- SF-Symbole und Apple-Logos außerhalb von Apple-Plattformen: ihre Lizenz verbietet es. Offene Symbol-Sets verwenden.
- Das Web- oder Android-Ergebnis „offizielles Liquid Glass“ nennen. Es ist eine Nachahmung im Stil.
Checkliste vor der Übergabe
Screenshots im Maßstab 2, selbst ansehen:
- Ruhe über einem Raster oder Text: Linien sind durch das transparente Glas sichtbar, am Rand zur Mitte gezogen, das Highlight ist dünn. Auf Weiß wird das Glas durch Randschattierung und Schatten von der Seite getrennt; auf Dunkel durch eine helle Linie auf der beleuchteten Seite.
- Drücken: der Button wuchs und neigt sich zum Finger; ein Daumen ist aufgebläht und transparent, die Spur zeigt durch ihn, der Regenbogen ist weich, keine farbigen Löcher.
- Ziehen: ein Daumen dehnt sich mit Geschwindigkeit und entleert sich erst nach Ankunft; die Tab-Leiste neigt sich und kehrt zurück. Der Tab-Leisten-Tropfen an Rand-Tabs und nahe der unteren Bildschirmkante: eigenes Element innen, Nachbarn an den Rändern, keine schwarzen Bereiche, Bänder oder gespiegelten Stücke.
- Ziehen: ein Button folgt dem Finger an einem Gummiband und springt zurück; eine zu einem benachbarten Button gezogene Leiste verschmilzt mit ihm, die Brücke wächst bei Annäherung, keine Naht oder Doppelrand; in Ruhe und bei einfachem Druck bleiben sie getrennt; ein normaler Tipp funktioniert, ein weit weg gezogener und losgelassener Button feuert nicht.
- Über einem Foto und über Weiß: Farbe unter dem Glas ist kräftig, Text ist lesbar.
- Dunkles Design.
- Fallback: die Engine vortäuschen (Safari User-Agent und leeres
navigator.userAgentData) und prüfen, dass Elemente nicht zu Löchern wurden und Symbole unter dem Tab-Leisten-Daumen nicht unscharf sind. - Größenänderung und Drehung: die Karte wird neu aufgebaut, keine Treppenstufen am Rand.
- Bildschirmübergänge: mehrere aufeinanderfolgende Bilder aufnehmen, während ein Bildschirm eintritt; Glas-Buttons sind nie dunkler als im Ruhezustand, Verschmelzungsebenen bleiben nach der Animation genau unter ihren Buttons.
- Keine Konsolenfehler und kein Hängen: nach einer Serie von Tipps reagiert die Seite genauso schnell. Eine Animationsschleife, keine verirrten
requestAnimationFrames. - Nicht mehr als 3 große Glaselemente auf einem Telefonbildschirm, kein Glas auf Glas, kein Glasinhalt.
Wenn etwas fehlschlägt, zuerst beheben, dann dem Benutzer zeigen.
Quellen
- Kyant0/AndroidLiquidGlass, Backdrop-Bibliothek und -Katalog (Apache-2.0): Linsen-, Dispersions-, Highlight- und Schattenformeln, Komponentenrezepte, Feder- und Gestenkonstanten. Die Web-Engine ist ein Port dieses Schemas.
- Apple: Human Interface Guidelines „Materials“, „Adopting Liquid Glass“, WWDC25 „Meet Liquid Glass“.
- kube.io, „Liquid Glass in the Browser“: Brechung durch
feDisplacementMapinnerhalb vonbackdrop-filter. - iyinchao/liquid-glass-studio (MIT): Verschmelzung von Formen via
smin, Snell-Brechung, farbloses Glas mit einem hohen
…
[gekürzt zur Übersetzung]