Blur craft
Das meiste Glas im Web sieht billig aus – aus drei Gründen: Dahinter passiert nichts Interessantes, das Material besteht aus einem einfarbigen Tönung mit einer Unschärfe, und der Text darauf ist ein matschiges Grau, das niemand gemessen hat. Glas, das teuer aussieht (Apples Materialien, visionOS, die besten Produktseiten), macht drei Dinge richtig, in dieser Reihenfolge:
- Das Licht hinter dem Glas ist gestaltet. Glas zeigt, was dahinter ist, also platziere dort ein Licht.
- Das Glas ist ein Material, keine Tönung. Gesättigte Unschärfe, eine Verlaufsfüllung, eine beleuchtete Kante, ein spiegelnder Glanz, Tiefe, Körnung. Das ist
assets/glass.css. - Der Text ist gemessen. Transluzentes Glas ändert den Kontrast mit jedem Pixel dahinter, daher wird der Kontrast an der schlechtesten Stelle geprüft, per Script, in drei Zuständen (
scripts/glass-contrast.mjs).
Schnellübersicht
| Ich baue … | Verwende | Hinweise |
|---|---|---|
| Eine sticky Navigationsleiste | .gs-bar (surfaces.css) | Erweiterter Hintergrund; füge gs-bar--on-scroll hinzu, um es erst nach dem Scrollen gläsern zu machen |
| Einen Player, Dock oder Pill über Kunst | .gs-dock.glass.glass--clear + liquid-glass.js | Klares Liquid Glass, eines pro Bildschirm; adaptiver Farbton bei stark wechselnder Kunst |
| Eine schwebende Karte oder ein Panel mit Text | .glass.glass--regular | thick über einem detaillierten Foto |
| Ein Menü, Popover oder Command-Bar | .gs-menu.glass | 32px über ~86%, 0,5px oberer Highlight |
| Einen Dialog | .gs-veil + .gs-dialog.glass.glass--thick | glass--solid wenn es um Geld, Löschen oder Unterschriften geht; gs-veil--flat + .gs-modal-open wenn Glas-Chrom darunter sitzt |
| Einen Toast oder ein Bottom-Sheet | .gs-toast.glass.glass--regular / .gs-sheet.glass.glass--thick | Die gs--Klassen sind nur Layout; das Material kommt von .glass |
| Inhalt, der unter einer Leiste verschwindet | Progressive Unschärfe (Rezept 2) | Ein Scroll-Kanten-Effekt pro Ansicht |
| Eine Überschrift, die erscheint, oder ein Wert, der sich ändert | Blur Reveal (4) / 2px Crossfade (4b) | Einmal pro Bildschirm |
| Eine Seite, die in den Farben der Kunst getaucht ist | Art-Backdrop, gebacken (Rezept 8) | Niemals eine Live-Unschärfe unter festem Glas |
| Ein Tailwind v4-Projekt | glass.css + glass.tailwind.css (glass-blur-24, …) | Tailwinds eigenes backdrop-blur-* bricht auf Sonoma Safari |
| Eine native App (SwiftUI, Flutter, React Native, Compose) | references/native.md | Gleiche Methode, jedes Toolkits Material |
| Chrom für einen Foto-, Video- oder Design-Editor | .glass.glass--thick.glass--neutral | Neutral: keine Sättigungssteigerung, das Glas darf die Arbeit nicht verfärben |
Danach: Komponiere das Licht (§1), setze das Material (§2), prüfe (§5). assets/demo.html zeigt jede Oberfläche live mit Bedienelementen; öffne es, um zu sehen, was jede Klasse bewirkt, bevor du dich entscheidest.
1. Zuerst das Licht komponieren
Entscheide, was direkt hinter jeder Glasoberfläche sein wird, und mache es zum Leuchtendsten dort.
-
Platziere ein Licht unter dem Glas: einen Glow, die Sonne in der Kunst, die Farben des Produkts, eine live WebGL-Komponente. Unscharfe, einfarbige Farbe ist dieselbe einfarbige Farbe; Glas über einer Leere ist eine graue Box.
-
Lass das Licht die Kante überqueren. Das beste Glas sitzt zur Hälfte über dem Licht und zur Hälfte über der Dunkelheit, sodass sich die Farbe über seine Breite verschiebt.
-
Richte die Kante auf das Licht aus. Setze
--glass-lightauf die Farbe des Lichts (255 200 160für einen Sonnenuntergang) und--glass-rim-angleauf seine Richtung. Das helle Ende der Kante zeigt zum Licht:Licht von oben-links oben oben-rechts rechts unten-rechts unten unten-links links Winkel 135deg 180deg 225deg 270deg 315deg 0deg 45deg 90deg Ein Licht unter dem Glas nimmt den Winkel seiner nächsten Kante plus ~15deg zur Mitte hin. Der Winkel ist eine registrierte
@property, sodass er dem Zeiger oder dem Scrollen sanft folgen kann (Apples Highlights wandern um das Material, während sich das Licht bewegt). -
Bemesse Glas wie den Helden, der es ist. Es liest sich als Material, wenn es groß genug ist, um die Szenenänderung darunter zu zeigen. Apple lässt größeres Glas sich wie dickeres Glas verhalten: tieferer Schatten, weichere Streuung.
2. Das Material setzen
Verwende assets/glass.css (benenne das glass-Präfix beim Kopieren um) und assets/surfaces.css für die vorgefertigten Oberflächen, oder die Komponenten: Glass.tsx (React), Glass.vue (Vue 3), Glass.svelte (Svelte 5). Schreibe keine einzeilige backdrop-filter-Karte von Hand.
Schreibe backdrop-filter mit Literalwerten, niemals var(), zuerst ohne Präfix und -webkit- zuletzt. Safari 18 und 26 unter macOS Sonoma rendert keine Unschärfe, wenn der Filter aus benutzerdefinierten Eigenschaften aufgebaut ist (WebKit 297620, offen), und Tailwind v4s backdrop-blur-* ist genau so aufgebaut. Derselbe Bugbericht zeigt, dass die unprefixierte Eigenschaft dort sogar mit einem Literalwert fehlschlägt, daher kommt die mit Präfix deklarierte zuletzt, wo Safari sie anwendet (Chrome und Firefox ignorieren sie). glass.css hat einen Literalfilter pro Dicke × Ton und wechselt per Klasse; Variablen sind für Füllungen, Abdunklungen und Farben in Ordnung.
Dicke. Wähle danach, wie viel Text das Glas trägt. Die Werte wurden mit dem Kontrastprüfer über einem hellen Licht in demo.html kalibriert:
| Klasse | Unschärfe, Abdunklung | Besteht 4.5:1 über hellem Licht? | Verwende für |
|---|---|---|---|
glass--clear | 16px, 22% | Nein: nur fett oder großen Text und Symbole | Docks, Play-Buttons, Pills über Medien (Apple: Clear benötigt fette, helle Inhalte und eine Abdunklungsschicht) |
glass--thin | 24px, 30% | Nicht über dem hellsten Licht | Steuerelemente, Chips, kleine Karten über moderaten Hintergründen |
glass--regular | 32px, 48% | Ja auf der Kalibrierungsseite; ein heller Sonnenuntergang hinter einem Player benötigte thick bei 0.62 | Player, Panels, Toasts: der Standard. Der Zustand ohne Unschärfe (nur Tönung) versagt meist zuerst |
glass--thick | 44px, 56% | Ja | Menüs, Sheets, Dialoge, alles Textlastige |
glass--solid | 4px, 92% | Ja | Zahlungen, Löschvorgänge, Unterschriften (über ~85% Füllung ist eine große Unschärfe nicht sichtbar, daher 4px) |
Füge glass--light für helles Glas mit tintenfarbenem Text hinzu und glass--neutral bei farbkritischen Apps (Foto-, Video- und Design-Editoren): keine Sättigungssteigerung oder Farbtonverschiebung, weil das Glas das Aussehen der Arbeit nicht verändern darf. Über einem detaillierten Foto starte mit thick und --glass-dim: rgb(10 10 18 / 0.65–0.75) (es ist eine Farbe, keine Zahl): lebendiges Glas und lesbarer Text ziehen dort gegeneinander, also gib die Lebendigkeit für die Kante, den Glanz und das um das Glas herumfließende Licht aus.
Zwei Stufen, wie iOS 26.1: eine getönte Stufe (mehr Deckkraft, niemals weniger) schaltet sich für prefers-contrast: more ein (die Einstellung, die Safari-Nutzer erreichen können; Safari hat kein prefers-reduced-transparency), mit glass--tinted, oder seitenweit mit <html data-glass="tinted">. glass.css behandelt auch Windows High Contrast (solide Canvas-Oberfläche), Druck (einfach gerahmte Box), Capture-Modus für Screenshot-Tools und RTL.
Glas gehört zur Steuerungsebene (Navigation, Symbolleisten, Docks, Menüs, Sheets, Dialoge), die über dem Inhalt schwebt, niemals zum Inhalt selbst, und niemals Glas auf Glas (Apple, WWDC25). Töne nur die primäre Aktion. Passe das Register des Briefings an: immersive Briefings nehmen starkes Licht und klares Glas auf der Heldensteuerung; vertrauenswürdige (Finanzen, Gesundheit) nehmen dickes oder solides Glas und kaum Licht.
references/material.md enthält den Rest: was jede Ebene tut und warum, die Presets aus Apple.com, Linear, Raycast, Radix, Material und Fluent, Apples vollständige WWDC25-Regelliste und die Registertabelle.
3. Signature-Effekte
Code in references/recipes.md:
- Liquid-Glass-Refraktion: Die Kante biegt, was dahinter ist, wie eine Linse, optional mit chromatischer Aberration (0.6–1). Zwei Versionen:
liquid-glass.ts/.jsbeugt jeden Seiteninhalt, aber nur in Chromium (Safari malt nichts für SVG-Hintergrundfilter, WebKit 245510);liquid-glass-webgl.jsbeugt einen Hintergrund, den die Seite selbst zeichnet (ein<canvas>,<img>oder<video>, z. B. ein Hero-Hintergrundbild) in jedem Browser, getestetes Rendering in Chromium und WebKit. Anderswo muss das matte Material für sich allein fertig aussehen. Refraktion und Mattierung tauschen gegeneinander ab: Die Biegung zeigt sich durch klares Glas (blur0–6); mattiertes (12–20) mattiert von Kante zu Kante und die Biegung wird zu einer sanften Farbverschiebung. Klar für ein Wort oder ein Symbol, mattiert für Sätze, Text einen Rahmenbreite innerhalb der Kante. Niemals auf einem Dialog über einem Schleier: Es gibt nichts Scharfes zum Biegen mehr. - Erweiterter Hintergrund für sticky Bars: Farbe kommt im Glas an, bevor Inhalt darunter scrollt.
gs-bar--on-scrollmacht die Leiste nur nach dem Scrollen gläsern, in reinem CSS (scrollgesteuerte Animationen). - Progressive Unschärfe: Inhalt löst sich unter einer Leiste auf, statt abgeschnitten zu werden. Gestapelte maskierte Ebenen sind der einzige Weg, bis CSS
linear-blur()erhält (vorgeschlagen, csswg #13285). - Blur-überbrückter Crossfade: 2px Unschärfe während eines Zustandswechsels (Emil Kowalski).
- Blur Reveal: von
blur(8px), einmal, als Ankunftsmoment. - Fokus-Schleier: Die Seite hinter einem Dialog tritt 4–8px zurück.
- Glas-Morph und Drücken: ein
layoutId-Morph zwischen nahen Glasformen (Cursor: 0.34s,[0.32, 0.72, 0, 1]) und ein Inner-Glow-Puls beim Drücken, keine Skalierung. - Verschmelzende Glasformen: eine Glasebene, geschnitten durch eine goo-gefilterte SVG-Maske, sodass nahe Formen mit einem flüssigen Hals verbunden werden, wie Apples Glasbehälter (Rezept 11, getestet in Chromium).
- Ambient-Glow aus Video: ein 10×6-Canvas-Sample des laufenden Videos, hochskaliert (Rezept 8b).
- Tönung: Chroma ~0.03–0.05 für strukturelles Glas, relativer Farb-Alpha für Tönungen (Rezept 12).
- Tiefenschärfe, Geschwindigkeitsbewegungsunschärfe, Kunst-Hintergrund (gebacken), gesperrter Inhalt, Körnung.
4. Halte es schnell
Gestalte zuerst das Aussehen, dann halte diese Punkte ein:
- Lange oder sich wiederholende Animationen finden auf Deckkraft und Transformation statt, nicht auf dem Unschärferadius. Kurze Einmal-Aktionen sind in Ordnung: Apple.com animiert die Unschärfe seines Menüvorhangs von 0 → 20px über 320ms.
- Verwische niemals zwei gestapelte Oberflächen gleichzeitig (Apples Navigation gibt ihre eigene Unschärfe auf, während ein Flyout geöffnet ist). Wenn ein Dialog über Glas-Chrom geöffnet wird, füge
.gs-modal-openzu<html>hinzu (das Chrom stoppt die Unschärfe und wird nahezu undurchsichtig) und verwendegs-veil--flat, oder backe den Schleier aus einem Bild- oder Canvas-Hintergrund. Gemessen in einem Fotoeditor-Test: ein Live-Vollbild-Schleier-Unschärfe über fünf Glaspanels lief mit 31fps; ohne sie 60. - Eine fixierte oder sticky Unschärfe wird bei jedem Scroll-Frame neu ausgeführt. Eine große pro Bildschirm; backe große unscharfe Bilder darunter (gemessen: 60 → 22fps mit Live-Unschärfe, zurück auf 60 gebacken).
- Telefone: sieben 18px-Panels kosten ~3,5ms pro Frame auf einem Mali-G57 (75–80% der Frames rechtzeitig vs. 99% ohne). Bei mehr als ein paar Panels entferne
backdrop-filteram Telefon-Breakpoint deines Layouts und behalte die transluzente Füllung (oder lassglass-tier.jspro Gerät entscheiden). - Budgetiere die unscharfe Fläche, nicht den Radius oder die Anzahl. Gemessen für diese Fähigkeit (Chromium, Software-Rendering bei 2×, bewegter Hintergrund, vsync an): Radius 4 → 64px und 1 → 9 Oberflächen bei derselben Gesamtfläche machte keinen Unterschied; das Verwischen von 90% des Bildschirms fiel auf 51fps (p95 33ms). Das stimmt mit Skia-Downsampling großer Unschärfen überein. Die Zahlen sind relativ (ein schneller Mac, der in Software rendert), das Ranking ist das, was übertragbar ist.
- Gib
htmleine undurchsichtige Hintergrundfarbe: Safari überspringt dann eine zusätzliche Vollbild-Compositing-Ebene für Seiten mit Glas (WebKit 271340: der Fix überspringt die Ebene nur für undurchsichtige Dokumente). - Verwische nicht unter einer undurchsichtigen Füllung. Framer und Dia liefern
backdrop-filterauf soliden Hintergründen und bezahlen für eine Unschärfe, die niemand sehen kann. Über ~85% Füllung verwende ≤ 4px oder keine (Arcs Toasts: 85% und 3px). - Stufe Glas nach Gerät:
assets/glass-tier.jssetztdata-glass-tierauf full, lite (eine 8px-Unschärfe) oder flat (keine Unschärfe, mehr Tönung) basierend auf Gerätespeicher, Save-Data, einem Frame-Rate-Sensor (iOS Low Power Mode begrenzt Animationen absichtlich auf 30fps) und Compute Pressure, so wie Android, Fluent und Apple Unschärfe auf schwachen oder energiesparenden Geräten entfernen. - Über Video: verwische nicht das laufende Video; sample es in eine winzige Canvas (Rezept 8b) und entferne Glas im Vollbildmodus. Safari übergibt niemals Videopixel an SVG-Filter.
- Hintergrund-Root: ein Elternelement mit
opacity < 1,filter, einer Maske,clip-path,mix-blend-mode,backdrop-filteroderwill-changeauf einem davon macht Glas darin flach. Das schließt ein Framer Motion-Eltern-Fade und einen goofilterauf einem Elternelement von Glas-Blobs ein. Fade das Glas selbst; entferne Reveal-Filter (filter: none), wenn sie fertig sind. backdrop-filtermacht ein Element zum Containing Block fürposition: fixed-Kinder: Portal-Menüs, Toasts und Dialoge aus Glasbehältern.- Ein stehender
view-transition-nameauf einem Vorfahren macht Glas in Chromium flach; setze Namen nur während des Übergangs. Framework-Fade-Übergänge auf einem Wrapper tun dasselbe: Fade das Glas selbst. - Screenshots, OG-Bilder oder PDFs von Glas: html2canvas, Satori und Druck entfernen oder brechen die Unschärfe. Setze
data-glass-captureauf<html>während des Aufnehmens (glass.css macht Glas undurchsichtig) und siehe quirks.md.
5. Prüfen (erforderlich)
Führe alle folgenden Schritte aus, bevor du das Glas als fertig bezeichnest:
- Frost-Check:
node <skill>/scripts/frost-check.mjs <url or file.html>misst für jede Glasoberfläche, wie viel Detail die Unschärfe entfernt (Unschärfe an vs. aus). NO BLUR bedeutet ein Hintergrund-Root, ein kaputtes Präfix odervar()oder eine veraltete Liquid-Glass-Karte; FLAT bedeutet, dass nichts dahinter zu messen ist. Um stattdessen mit dem Auge zu prüfen, setze fetten roten Text hinter das Glas, erfasse beideviceScaleFactor: 1und vergrößere. - Kontrast, gemessen, auf dem schlechtesten Hintergrund:
node <skill>/scripts/glass-contrast.mjs <url or file.html>. Richte es auf den hellsten realistischen Zustand, nicht den hübschen Standard: das hellste Foto, einen Tageslicht-Frame, ein um +2 EV angehobenes Bild, den weißen Seitenabschnitt, der unter die Leiste scrollt (füge URL-Parameter oder einen Testzustand hinzu, damit das Skript ihn laden kann). Bei einem Editor bestand das Standardfoto bei 8.7:1 und ein heller Frame fiel bei 4.4:1 durch. Prüfe auch die Telefonbreite (--width 390 --height 844). Es versteckt den Text, findet den hellsten und dunkelsten Pixel unter jeder Zeile und prüft 4.5:1 (3:1 groß) in drei Zuständen: normal, nur Tönung (Unschärfe aus, wie iOS Low Power Mode es zeigt) undprefers-contrast: more. Behebe Fehler, indem du eine Dicke höher gehst, den Alpha in--glass-dimerhöhst (z. B.--glass-dim: rgb(10 10 18 / 0.7)) oder die Glasfüllung mehr zur undurchsichtigen Seite verschiebst, ohne den Materialcharakter zu verlieren: Die Grenze liegt bei etwa 75–80% je nach Textgröße. Wenn der Text auf der Tönung allein besteht, das Glas aber auf der Unschärfe angewiesen ist, um lesbar zu sein, entferne die Unschärfe auf diesem Gerät vollständig (flat) und gleiche mit mehr Tönung aus.
assets/demo.html öffnet jede Oberfläche live mit Bedienelementen für die Dicke, den Lichtwinkel und die Prüfungen.