4 Punkte von GN⁺ 2024-11-25 | 1 Kommentare | Auf WhatsApp teilen
  • Ausgehend von der frosted acrylic UI in Forza Horizon 3 und Forza Motorsport 7 wird beschrieben, wie sich ein ähnlicher Glaspanel-Effekt im Web mit HTML/CSS/JavaScript nachbilden lässt
  • Im Mittelpunkt des Effekts steht Gaussian blur; um Browserunterschiede zu verringern, sollten CSS backdrop-filter und für iOS -webkit-backdrop-filter gemeinsam verwendet werden
  • Da reine Unschärfe flach wirken kann, werden mit box-shadow: inset Kantentiefe und subsurface scattering ergänzt; ein normaler Schatten erzeugt den Eindruck, über dem Hintergrund zu schweben
  • Oberflächenreflexionen werden über ein Lichtstrahlen-Bild als separate Ebene umgesetzt; mit background-attachment: fixed oder JavaScript wird eine dynamische Reflexion simuliert, die zur Bewegung des Glases passt
  • Die finale UI kombiniert die Ebenen .glass, .light und .drag-me und wird mit abgerundeten Ecken, Clipping und halbtransparenter Hintergrundfarbe zu einer kopierbaren Glaskomponente fertiggestellt

Glaspanel-Effekt aus Game-UIs

  • Ziel ist es, das frosted acrylic design aus der UI-Entwicklungserfahrung mit Forza Horizon 3 und Forza Motorsport 7 in HTML nachzubilden
  • Das Ergebnis ist ein ziehbares Glaspanel mit Hintergrundunschärfe, Kantentiefe, Lichtreflexionen, abgerundeten Ecken und einer halbtransparenten Farbebene
  • Zu Beginn wird ein finales Rezept bereitgestellt, das sich direkt kopieren lässt; anschließend werden die einzelnen Effekte Schritt für Schritt aufgebaut

Hintergrundunschärfe mit backdrop-filter

  • Der Kern eines guten Frosted-Glass-Effekts ist Gaussian blur, der den Hintergrund unscharf macht und ihn wie einen halbtransparenten Screen erscheinen lässt
  • In CSS wird das durch Anwendung von blur auf backdrop-filter umgesetzt
  • Das grundlegende Glaselement beginnt mit einem einfachen div und der Klasse .glass
    • backdrop-filter: blur(10px)
    • -webkit-backdrop-filter: blur(10px)
  • Unter iOS ist -webkit-backdrop-filter nötig, sofern man nicht tiefergehende separate Einstellungen ändert
  • Da backdrop-filter erst seit Kurzem von Browsern unterstützt wird, können Nutzer von Internet Explorer die Demo nicht erleben

Tiefe durch Kanten und Schatten erzeugen

  • Wenn nur backdrop-filter: blur(10px) angewendet wird, kann das Glas flach und eintönig wirken
  • Die Kanten werden nicht mit border: 1px solid, sondern mit box-shadow: inset umgesetzt
    • border beeinflusst die Elementgröße und die Positionierung von Kindelementen
    • Mit box-shadow: inset können Kindelemente den Inhaltsbereich des Glases natürlich ausfüllen, ohne Anpassungen wie negative Margins
  • Zwei halbtransparente weiße inset shadows stellen die Glaskanten dar
    • Der erste Schatten steht für die von außen sichtbare Glaskante; im Beispiel erscheint er an der unteren und linken Kante
    • Der zweite Schatten steht für die durch das Glas sichtbare Kante; im Beispiel erscheint er an der oberen und rechten Kante
  • Die durch das Glas sichtbare Kante wird weicher und transparenter eingestellt, da das Licht dabei abnimmt
  • Ein normaler dunkler box-shadow kann dem Glas den Eindruck geben, physisch über dem Hintergrund zu schweben

Lichtstreuung und Oberflächenreflexion

  • Das Gefühl, dass sich Licht im Inneren des Glases ausbreitet, wird durch eine vereinfachte Darstellung von subsurface scattering erzeugt
  • Für die Umsetzung wird erneut box-shadow: inset verwendet
    • Kurzer Streueffekt: inset 0px 0px 10px 5px rgba(255, 255, 255, 0.025)
    • Tieferer Streueffekt: inset 0px 0px 40px 5px rgba(255, 255, 255, 0.025)
  • Dieser Effekt ist besser sichtbar, wenn das Glas über einen dunklen Hintergrund gezogen wird
  • Zusätzlich zum Eindruck eines unscharfen, gebrochenen Hintergrunds wird auch die Eigenschaft ergänzt, dass Licht von der Glasoberfläche reflektiert wird
  • Die Lichtreflexion wird umgesetzt, indem ein Lichtstrahlen-Bild als Hintergrund eingemischt wird
    • Zum Erstellen eines ähnlichen Bildes gibt es ein YouTube-Tutorial und eine Textanleitung
    • Wenn das Bild direkt als background-image in das .glass-Element eingefügt wird, macht backdrop-filter das Bild unscharf; daher wird eine separate Ebene wie ::before verwendet

Statische Reflexion dynamisch machen

  • Wenn nur ein Lichtstrahlen-Bild darübergelegt wird, entsteht zwar eine Reflexion, aber beim Bewegen des Glases kann es so wirken, als wäre das Licht auf der Glasoberfläche fixiert
  • Der reine CSS-Ansatz ergänzt background-attachment: fixed auf ::before
    • Die Umsetzung ist einfach, funktioniert aber möglicherweise nicht auf allen Plattformen
  • Damit es auf allen Plattformen funktioniert, wird background-attachment: fixed mit JavaScript imitiert
    • Da es ineffizient ist, ::before direkt aus JavaScript zu steuern, wird ein separates div.light-Element verwendet
    • Das Zielelement erhält das Attribut data-js-background-attachment-fixed
  • JavaScript liest in jedem Animationsframe den Wert von getBoundingClientRect() des Zielelements und aktualisiert background-position in die Gegenrichtung der Position im Viewport
    • backgroundPositionX = -clientRect.x
    • backgroundPositionY = -clientRect.y
  • Die Wiederholungsschleife läuft über requestAnimationFrame

Finale HTML/CSS-Struktur

  • Das finale HTML der JavaScript-Version hat eine Struktur, bei der .glass die .light-Ebene für Lichtreflexionen sowie .drag-me als Text-/Farbebene enthält

  Drag Me

  • .glass übernimmt die Grundform und die visuellen Effekte des Glaspanels
    • Anwendung der Hintergrundunschärfe mit backdrop-filter und -webkit-backdrop-filter
    • Anwendung von Kanten, Schatten und Streueffekten mit mehreren box-shadow-Werten
    • position: relative, damit Kindelemente den Elternbereich ausfüllen können
    • Abgerundete Ecken mit border-radius: 5px
    • overflow: hidden, um Kindelemente abzuschneiden, damit sie nicht über die abgerundeten Ecken hinausragen
  • .light verwendet das Lichtstrahlen-Bild als wiederholten Hintergrund
    • background-image: url(path/to/light.png)
    • background-repeat: repeat
    • background-size: 750px
    • opacity: 0.075
    • Füllt mit position: absolute und Offsets von 0 in alle vier Richtungen den gesamten Elternbereich aus
    • Rendert mit z-index: -1 hinter den anderen Kindelementen
  • .drag-me zentriert den Inhalt und erzeugt eine farbige, halbtransparente Glasebene
    • display: flex
    • align-items: center
    • justify-content: center
    • height: 30px
    • background-color: rgba(12, 13, 14, 0.75)

Unterschied der Version ohne JavaScript

  • Die Version ohne JavaScript verwendet statt eines separaten .light-Elements .glass::before
  • Auf ::before wird das Lichtstrahlen-Bild angewendet, und mit background-attachment: fixed wird eine auf dem Bildschirm fixierte Reflexion umgesetzt
  • Dieser Ansatz funktioniert nicht auf allen Plattformen; die JavaScript-Version gleicht das aus, indem sie background-position direkt aktualisiert

1 Kommentare

 
GN⁺ 2024-11-25
Hacker-News-Kommentare
  • Ästhetisch gefällt es mir wirklich gut, aber an den Rändern gibt es Stellen, die physikalisch nicht ganz passen.
    Aus Sicht eines Embedded-Entwicklers wirkt es etwas verschwenderisch. Es fühlt sich so an, als würde jeder Client jedes Mal einen „teuren“ Blur-Filter berechnen, nur um ihn mit einer unscharfen Version des Hintergrundbilds zu mischen.
    Da es die GPU nutzt und optimiert ist, ist es am Ende vielleicht kein großer Kostenfaktor, aber Webentwicklung wirkt heute insgesamt wie ein Trend zu immer mehr Aufblähung. Selbst einfache Sites laden fünf Sekunden lang und wälzen schwere Verarbeitung auf den Client ab – was natürlich nicht die Schuld des Autors dieses Beitrags ist.

    • Was man als Verschwendung ansieht, hängt wohl von den eigenen Vorannahmen ab.
      Ich bin in der Zeit der 14,4k-Modems aufgewachsen und daran gewöhnt, Netzwerkbandbreite als viel knapper und teurer zu betrachten als CPU-Zeit.
      Wenn sich etwas leicht auf dem Client berechnen lässt, halte ich es für verschwenderischer, das komplette Bild über das Internet herunterzuladen. Dafür müssen Router, Server und entfernte Festplatten arbeiten; all das aufzuwenden, nur um eine Verarbeitung auf Daten zu vermeiden, die bereits im RAM des Clients liegen, erscheint mir noch unnötiger.
    • Websites, die technisch gesehen in mancher Hinsicht „verschwenderisch“ sind, dienen in ihrer tatsächlichen Nutzung im größeren Bild meist reiner Unterhaltung.
      Also ist entweder Unterhaltung selbst Verschwendung, oder es ist in Ordnung, mehr Rechenleistung einzusetzen, um Unterhaltung besser zu machen.
    • Aus menschlicher Sicht sieht es nach „gerenderte Grafik umfangreich neu berechnen“ aus und fühlt sich daher verschwenderisch an, technisch ist es aber nicht unbedingt so.
      Wenn sich in einer UI etwas ändert, braucht man ohnehin GPU-Berechnungen zum Neuzeichnen, und ein einfacher Blur lässt sich ziemlich effizient hinzufügen. Wahrscheinlich ist das günstiger als Animationen von DOM-Objekten, die nicht als GPU-Layer optimiert sind.
      Wenn heute selbst die simpelsten Sites über 1 MB JavaScript und massenhaft Tracker laden und damit CPU verbrauchen, steht ein Blur für ästhetische Effekte auf der Verschwendungsliste ziemlich weit unten.
    • Sowohl das geblurte als auch das Originalbild übers Netzwerk zu schicken, ist doch im Grunde das, was die Webentwicklung in den letzten 20 Jahren gemacht hat.
      Bei vielen hochauflösenden Bildern ist die reale Netzwerkbandbreite begrenzt, und besonders in mobilen Umgebungen mit schlechter Funkabdeckung ist das eindeutig langsamer als lokale Berechnung. Es ist erstaunlich, was heute allein mit CSS/WebGL möglich ist; früher brauchte man für solche Effekte viele Hacks und Workarounds.
    • Es ist Zeit, ernsthaft zu akzeptieren, dass viele Technologien nach dem Motto „Oh, sieht cool aus, das brauchen ich/wir bestimmt“ in dieser Welt keinen Platz haben.
      Unabhängig davon, ob die Handlung selbst Verschwendung ist, zeigt schon diese Denkweise ein größeres gesellschaftliches Problem. Warum brauchen wir das, und warum gilt der Zustand ohne das als schlecht?
      Angesichts des Ausmaßes heutiger gesellschaftlicher Probleme frage ich mich, wen es interessiert, ob ein UI-Panel verschwommen ist oder nicht.
  • Als ich auf Android ausprobieren wollte, was man mit der neuen Shader-API machen kann, habe ich den Windows 7 Aero Glass-Effekt nachgebaut und dabei eine ähnliche „Lichtstreifen“-Textur extrahiert.
    Das Ergebnis war diesem Beitrag sehr ähnlich, allerdings ohne inneren Schatten, und die Sättigung des unscharfen Hintergrunds habe ich etwas erhöht.
    https://mastodon.social/@grishka/110524476584503201

    • Sehr schön. Die Lichtstreifen-Textur kann bei diesem Effekt tatsächlich viel bewirken.
      Ehrlich gesagt ist die für das Tutorial erstellte Version gar nicht so großartig. Mir gefallen die schärferen Linien aus Windows 7 besser.
      Über eine Sättigungsanpassung habe ich ebenfalls nachgedacht und sie auch in anderen Beispielen gesehen, mich aber entschieden, sie im Artikel nicht zu verwenden. Das verwendete Mondbild hatte nicht besonders viele Farben, daher hätte es wohl keinen großen Unterschied gemacht. Wer selbst einen Glaseffekt baut, sollte auch mit der Sättigung experimentieren.
  • Die Arbeit selbst ist hervorragend, und auch die Präsentation als interaktive Demo ist gut. Es macht Spaß, das Fenster über den Mond zu ziehen.
    Allerdings mag ich den Einsatz von Milchglas-Effekten im User-Interface-Design nicht, und als sie in Mac OS hinzugefügt wurden, empfand ich das als Rückschritt. Designer lassen sich von diesem Effekt viel zu leicht verführen, aber ideal ist er in der Praxis nie – besonders dann nicht, wenn der Inhalt hinter dem Panel dynamisch oder nutzergeneriert ist.
    Er ist so etwas wie Brushed Metal der 2010er, und es ist erstaunlich, dass er aus Windows Vista herausgesickert ist und sich überall verbreitet hat.

    • Ich verstehe nicht, warum er „nicht ideal“ sein soll. Bei visuellem Design geht es zu einem großen Teil eher um persönliche Vorlieben dafür, was gut aussieht, als um praktische Zwecke.
      Natürlich beeinflusst Design auch die Funktion, aber sein Hauptzweck ist es, die User Experience angenehmer zu machen.
      Meiner Ansicht nach macht Skeuomorphismus Interfaces angenehmer als der minimalistische Trend der letzten über zehn Jahre, alles flach zu machen. Visuelle Verzierungen, die Oberflächen und Materialien der realen Welt nachahmen, schaffen Vertrautheit und Zugänglichkeit. Auch praktisch gesehen macht Flat Design es schwieriger, Elemente und Zustände zu unterscheiden, während es in Zeiten von 3D-Buttons, Brushed Metal und Milchglas viel klarer war.
      Ich denke, das Pendel schwingt jetzt wieder zurück. Da immer mehr Designer flache Optik vermeiden, hoffe ich auf eine Rückkehr menschenfreundlicherer UIs.
    • Ich bin kein UI-Designer, daher eine ernst gemeinte Frage: Ist das Problem der Einsatz von ästhetischen Effekten wie Milchglas oder Brushed Metal im UI-Design an sich, oder liegt es daran, dass manche Designer beim Bau solcher Interfaces die visuellen Hinweise verlieren, die Position und Funktion von Controls vermitteln?
    • Ich nutze seit Jahren eine leichte Transparenz in Terminalfenstern, aber jetzt bringt mich das zum Nachdenken.
    • Brushed Metal beeinflusst den Informationskontext nicht. Blur bietet einen steuerbaren Kontext.
      Blur ist meistens nicht die richtige Antwort, aber manchmal ist er die passende Wahl.
    • Ironischerweise haben auch frühere macOS-Versionen viel Brushed Metal verwendet.
  • 2008 gab es, bevor CSS backdrop-blur unterstützte, schon ein CSS-Experiment für einen ähnlichen Effekt: https://webdev.andersriggelsen.dk/aero/
    Dabei wurde ein Glaseffekt auf ein fest positioniertes, vorab weichgezeichnetes Hintergrundbild gelegt: https://webdev.andersriggelsen.dk/aero/bgl.jpg
    Das ist deutlich performanter als ein Echtzeit-Gaussian Blur, hat aber weiterhin den Nachteil, dass es keine dynamischen Hintergrundbilder erlaubt

    • Noch früher bin ich einmal einen Schritt weiter gegangen und habe eine Flash-Datei als Hintergrund verwendet
      So ließ sich der Glaseffekt sogar in einem Frame erzeugen, der sich dynamisch bewegen konnte. Ich erinnere mich nicht, ob ich dafür ein iframe verwendet habe, müsste also den Code suchen; wenn man die damalige Zeit bedenkt, ist es aber ziemlich wahrscheinlich
    • Das schwebende Fenster wird nach seiner Anfangsposition nicht mehr aktualisiert
      Es ist Windows 10 19045.5131, und Chrome ist die aktuelle Version 131.0.6778.86 (Official Build) (64-bit)
  • Die technische Leistung ist beeindruckend, aber ich halte es für schlechte UX
    Inhalte in halbtransparenten Panels sind schwerer zu lesen oder zu erfassen als vor einem einheitlichen, einfarbigen Hintergrund; der Kontrast zum Hintergrund ist gering und ungleichmäßig. Außerdem kann es ablenken und die Orientierung erschweren, wenn sich darunter etwas bewegt

    • Es ist schwer, einen einzelnen visuellen Effekt pauschal als „schlechte UX“ zu bezeichnen. Es hängt stark davon ab, wie er integriert wird
      Bei guter Integration sollte man die Intensität des Effekts so steuern, dass die UI nicht überladen wirkt, die Feature-Unterstützung prüfen, um zusätzliche Ausschmückungen zu vermeiden, wenn Blur nicht unterstützt wird, und die Display- und Grafikfähigkeiten prüfen, um auf Geräten, deren GPU möglicherweise nicht ausreicht, nicht zu rendern
      Außerdem sollte man Nutzereinstellungen berücksichtigen, um Nutzern, die mit komplexen Hintergründen Schwierigkeiten haben, eine kontrastreiche Vollfarbe anzubieten; den Umfang von Effekten und Schatten je nach verfügbarem Platz begrenzen; und Blur sowie Opazität an die Komplexität und den Kontrast des Hintergrunds unter dem verschwommenen Bereich anpassen
      Auch muss sichergestellt werden, dass Blur und Schatten passend zur Typografie adaptiv skalieren. UX ist im Kern das Design dafür, wie Nutzer die Interaktion mit der gesamten App erleben; sie entscheidet sich nicht am Erfolg oder Scheitern einer einzelnen Stilentscheidung
    • Windows Vista löste dieses Problem, indem schwarzer Text auf gefrostetem Glas eine konturartige weiße Schattenlinie bekam
      Das stellt die Lesbarkeit des Textes selbst im Extremfall eines schwarzen Hintergrunds sicher. In CSS lässt sich das mit der Eigenschaft text-shadow nachbilden
    • Deshalb setze ich diesen Effekt nicht auf meiner ganzen Website ein. Es ist schwieriger, damit gute UX zu schaffen
      In Spielen gibt es dafür aber mehr Einsatzmöglichkeiten. Besonders in einem HUD, bei dem man den Hintergrund als Hauptbereich der Nutzerinteraktion nicht verdecken möchte, kann es passend sein
    • Wenn geringer Kontrast das Problem ist, kann man den Hintergrund oder die Glastönung dunkler machen und den Vordergrundinhalt heller, oder umgekehrt
      Guter Kontrast ist bei jedem Designelement eine Herausforderung, egal ob Vollfarbe oder Glaseffekt
      Dass Vorgänge im Hintergrund ablenken und die Orientierung erschweren, ist ebenfalls sehr subjektiv. Genau wie man die Opazität einer Vollfarbe verringern kann, lässt sich auch die Transparenz des Glases reduzieren
      Diese Kritik ist schwerlich objektiv wahr; es gibt Möglichkeiten, dieses Designelement zu integrieren und solche Probleme zu vermeiden. Der Forza-Screenshot sieht in Ordnung aus, und auch in der tatsächlichen Ansicht fand ich den Hintergrund nicht ablenkend. Stattdessen bekommt man eine UI, die interessanter und visuell ansprechender ist als ein einfarbiger Hintergrund. In Videospielen mag das wichtiger sein, aber auch im OS- und Webdesign lässt es sich geschmackvoll einsetzen
    • Blur ist eine Methode, Informationen zu verbergen und dabei so viel Kontext zu erhalten, wie man steuern möchte
      Wenn viel Kontext nötig ist, ist Blur keine gute Wahl; wenn gar kein Kontext nötig ist, ebenfalls nicht
      Manchmal ist es aber eine ausgezeichnete Wahl
  • Das interaktive Beispiel ist gut, aber noch besser wäre ein Toggle gewesen, mit dem man es neben der vorherigen Stufe vergleichen oder zwischen beiden wechseln kann
    In den meisten Stufen waren die Verbesserungen so subtil, dass der Unterschied schwer zu erkennen war

    • Zustimmung. Auf Mobilgeräten ist ab der zweiten Stufe kaum noch ein Unterschied zu sehen oder überhaupt wahrnehmbar
  • Da liegen etwa zehn Effekte übereinander, und wenn man nicht die anspruchsvollste Ästhetik anstrebt, sind ungefähr sieben davon zu viel
    Hintergrundfarbe, Blur und etwas Schatten oder Rahmen reichen aus

    • Wer einen weniger schweren Glaseffekt möchte, kann sich aus dem Tutorial die passenden Teile herauspicken
      Schon in der dritten Stufe entsteht nur mit Blur und Schatten ein ziemlich ordentliches Stück Glas. Persönlich würde ich empfehlen, dazu ein statisches Bild mit Lichtstreifen zu mischen. Für die meisten Anwendungen dürfte der vollständige JavaScript-Effekt nicht nötig sein. Er macht Spaß, kann aber ablenken
      Allein mit Blur, Schatten und Lichtstreifen kommt man dem Forza-Bild ganz oben wirklich nahe
    • Interessant, dass die meisten Top-Kommentare von Verschwendung sprechen
      Ich denke, das ist einer der Gründe, warum alle zu Flat Design gewechselt sind. Windows Vista und Glaseffekte sahen toll aus, waren aber rechnerisch teuer
      Flat Design ist ästhetisch umstritten und kann besonders für ältere Nutzer schwieriger zu verwenden sein als skeuomorphes Design [0][1]
      Wenn Realismus die Benutzbarkeit unterstützen kann, halte ich den Einsatz solcher Effekte im Web für durchaus sinnvoll
      [0]: https://www.tandfonline.com/doi/abs/10.1080/0144929X.2020.18...
      [1]: https://www.sciencedirect.com/science/article/abs/pii/S01419...
    • Ich frage mich, warum die Grenze für übereinandergelegte Effekte bei n <= 3 liegen soll
      Ich weiß nicht, ob es um Barrierefreiheit, Performance, Wartbarkeit oder etwas anderes geht
      CSS ist mit Abstand meine schwächste Entwicklerkompetenz, deshalb kenne ich Best Practices und Anti-Patterns überhaupt nicht
    • Hast du nicht den Teil übersehen, in dem der Autor erklärt, dass er auf die anspruchsvollste Ästhetik abzielt?
  • Interessant, es fühlt sich an, als hätten wir uns einmal komplett im Kreis gedreht
    Eine der frühen CSS-Demos, eine Demo für CSS 1, war ein Frosted-Glass-Effekt: https://meyerweb.com/eric/css/edge/complexspiral/glassy.html

  • Ehrlich gesagt ziemlich beeindruckend. Es macht immer wieder Spaß zu sehen, wie kreativ und leistungsfähig CSS sein kann.
    Allerdings fühlt es sich so an, als gäbe es bei HTML/CSS eine Ebene, die ich niemals verstehen werde. Diese Demo ist genau so ein Fall: Diese Person baut ein mattiertes Fenster, und ich bekomme immer noch kein einzelnes div zentriert.

    • Als ich gelernt habe, wie Webentwicklung funktioniert, habe ich auf die harte Tour gelernt, dass es oft eine gute Idee ist, einfach noch ein div hinzuzufügen.
      Wenn man sich die meisten modernen Websites anschaut, sind divs dort wie riesige Haufen übereinandergestapelt. Wenn man ein zentriertes div möchte, wird es vergleichsweise einfach, wenn man darin noch ein div erstellt, das den gesamten Bereich einnimmt, in dem zentriert werden soll.
      Viele visuelle Tricks funktionieren ähnlich, aber dieses Beispiel ist sehr sauber umgesetzt und deshalb noch beeindruckender.
  • Es ist nicht exakt mattiertes Glas, aber ich habe in die Sidebar von https://www.gyan.dev/ffmpeg/builds/ einen Glasfenster-Effekt eingebaut.

    • Auf dem PC wirkt die Website sehr angenehm und hübsch.