Liquid Glass in SwiftUI: Der vollständige Guide für iOS 26

Lerne, wie du Liquid Glass in SwiftUI für iOS 26 einsetzt — vom glassEffect-Modifier über GlassEffectContainer und Morphing-Animationen bis hin zu Migration, Performance-Tipps und Barrierefreiheit.

Was ist Liquid Glass?

Mit iOS 26 hat Apple die wohl größte visuelle Überarbeitung seit iOS 7 eingeführt: Liquid Glass. Dieses neue dynamische Material kombiniert die optischen Eigenschaften von echtem Glas mit einem Gefühl von Flüssigkeit — und ehrlich gesagt, es verändert grundlegend, wie wir Oberflächen in unseren Apps gestalten.

Im Kern ist Liquid Glass ein transluzentes Material, das den darunter liegenden Inhalt in Echtzeit bricht und reflektiert. Anders als der klassische Blur-Effekt, den wir von .ultraThinMaterial kennen, nutzt Liquid Glass ein sogenanntes Lensing — es biegt und konzentriert Licht, anstatt es zu streuen. Dazu kommen spiegelnde Highlights, die auf Gerätebewegungen reagieren, adaptive Schatten und interaktive Verhaltensweisen bei Touch-Events. Klingt beeindruckend? Ist es auch.

Das Designsystem erstreckt sich plattformübergreifend über iOS 26, iPadOS 26, macOS Tahoe 26, watchOS 26, tvOS 26 und visionOS 26. Für uns SwiftUI-Entwickler heißt das: Ein einheitliches API-Set für alle Apple-Plattformen. Endlich.

Automatische Übernahme: Was sich von selbst ändert

Sobald du deine App mit Xcode 26 und dem iOS 26 SDK neu kompilierst, übernehmen viele System-Komponenten den Liquid-Glass-Look automatisch — ohne eine einzige Zeile Code zu ändern:

  • NavigationBar, TabBar und Toolbar — erhalten transparente Glasoberflächen
  • Sheets, Popovers, Menüs und Alerts — nutzen das neue Material
  • Suchleisten und Control Center — passen sich an
  • Toggles, Slider und Picker — zeigen während der Interaktion Glaseffekte

Das ist erst mal großartig — deine App sieht sofort moderner aus. Aber (und das ist ein wichtiges Aber) du solltest trotzdem prüfen, ob die automatischen Änderungen zu deinem bestehenden Design passen. Falls nicht, kannst du die Kompatibilitäts-Flag UIDesignRequiresCompatibility in deiner Info.plist auf YES setzen, um den alten Look beizubehalten.

Grundlagen: Der glassEffect-Modifier

Für eigene Views ist der .glassEffect()-Modifier dein Einstiegspunkt. So sieht die vollständige Signatur aus:

func glassEffect<S: Shape>(
    _ glass: Glass = .regular,
    in shape: S = DefaultGlassEffectShape,
    isEnabled: Bool = true
) -> some View

Im einfachsten Fall reicht ein einziger Aufruf:

import SwiftUI

struct BasicGlassView: View {
    var body: some View {
        Text("Hallo, Liquid Glass!")
            .padding()
            .glassEffect()
    }
}

Standardmäßig wird der Glaseffekt in einer Capsule-Form hinter deinem Inhalt gerendert. SwiftUI passt die Textfarbe automatisch an, damit sie auch vor farbigen Hintergründen gut lesbar bleibt. Ein nettes Detail, das dir einiges an Arbeit abnimmt.

Die drei Glass-Varianten

Die Glass-Struktur bietet drei statische Varianten, die du je nach Kontext einsetzen kannst:

  • .regular — Der Standard. Ein deutlich sichtbarer Glaseffekt mit moderater Transparenz. Ideal für Navigation und prominente UI-Elemente
  • .clear — Subtiler und durchsichtiger. Gut für sekundäre Elemente oder Container, die weniger Aufmerksamkeit beanspruchen sollen
  • .identity — Kein visueller Glaseffekt, aber das Layout bleibt erhalten. Perfekt für Barrierefreiheits-Fallbacks
// Regular — deutlich sichtbar
Text("Primär")
    .padding()
    .glassEffect(.regular)

// Clear — dezenter
Text("Sekundär")
    .padding()
    .glassEffect(.clear)

// Identity — kein visueller Effekt
Text("Fallback")
    .padding()
    .glassEffect(.identity)

Tinting: Glaseffekte einfärben

Mit der .tint()-Methode kannst du den Glaseffekt farblich anpassen. Das ist besonders praktisch, um visuelle Hierarchien zu schaffen oder dein Branding einzubinden:

// Blauer Tint
Text("Info")
    .padding()
    .glassEffect(.regular.tint(.blue))

// Dezenter lila Tint mit Transparenz
Text("Hinweis")
    .padding()
    .glassEffect(.regular.tint(.purple.opacity(0.6)))

// Branding-Farbe
Text("Marke")
    .padding()
    .glassEffect(.regular.tint(Color("BrandColor")))

Wichtig zu wissen: Der Tint beeinflusst nur den Glaseffekt selbst — er überschreibt nicht die Textfarbe. SwiftUI wählt weiterhin automatisch eine gut lesbare Vordergrundfarbe. Das musst du also nicht manuell regeln.

Formen anpassen

Die Form des Glaseffekts lässt sich über den zweiten Parameter steuern. SwiftUI bietet sowohl eingebaute als auch benutzerdefinierte Shapes:

// Capsule (Standard)
.glassEffect(.regular, in: .capsule)

// Kreis — ideal für runde Buttons
.glassEffect(.regular, in: .circle)

// Abgerundetes Rechteck mit eigenem Radius
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))

// Container-konzentrische Ecken
.glassEffect(.regular, in: .rect(cornerRadius: .containerConcentric))

Die Option .containerConcentric ist dabei besonders clever: Sie passt den Eckradius automatisch an den umgebenden Container an, sodass verschachtelte Glaselemente visuell harmonisch wirken. Das spart dir manuelle Berechnungen — was ich persönlich sehr schätze.

Eigene Shapes verwenden

Du kannst auch komplett eigene Shapes definieren und als Glasform nutzen:

struct AbgerundetesPolygon: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let breite = rect.width
        let hoehe = rect.height
        path.move(to: CGPoint(x: breite * 0.5, y: 0))
        path.addLine(to: CGPoint(x: breite, y: hoehe * 0.35))
        path.addLine(to: CGPoint(x: breite * 0.8, y: hoehe))
        path.addLine(to: CGPoint(x: breite * 0.2, y: hoehe))
        path.addLine(to: CGPoint(x: 0, y: hoehe * 0.35))
        path.closeSubpath()
        return path
    }
}

// Verwendung
Image(systemName: "star.fill")
    .font(.largeTitle)
    .frame(width: 100, height: 100)
    .glassEffect(.regular, in: AbgerundetesPolygon())

Interaktive Glaseffekte

Jetzt wird's richtig spannend. Für tappbare Elemente wie Buttons oder Controls bietet Liquid Glass interaktive Verhaltensweisen — Skalierung, Bounce und ein subtiles Schimmern bei Berührung. Aktiviert wird das mit .interactive():

struct InteraktiveGlasButtons: View {
    var body: some View {
        HStack(spacing: 20) {
            Button(action: { /* Aktion */ }) {
                Image(systemName: "heart.fill")
                    .font(.title2)
                    .frame(width: 56, height: 56)
            }
            .glassEffect(.regular.interactive(), in: .circle)

            Button(action: { /* Aktion */ }) {
                Label("Teilen", systemImage: "square.and.arrow.up")
                    .padding(.horizontal, 16)
                    .padding(.vertical, 10)
            }
            .glassEffect(.regular.interactive())
        }
    }
}

Die Regel ist simpel: Verwende .interactive() nur bei Elementen, die der Nutzer auch tatsächlich antippen kann. Dekorative Glasflächen sollten nicht interaktiv sein — das verwirrt sonst die Nutzererwartung.

Eingebaute Button-Styles

SwiftUI bringt außerdem zwei dedizierte Glass-Button-Styles mit:

// Transparenter Glass-Button — für sekundäre Aktionen
Button("Abbrechen") { }
    .buttonStyle(.glass)

// Opaker, prominenter Glass-Button — für primäre Aktionen
Button("Speichern") { }
    .buttonStyle(.glassProminent)

Gerade .glassProminent finde ich super für Call-to-Action-Buttons — er sticht hervor, ohne den typischen Liquid-Glass-Look zu verlieren.

GlassEffectContainer: Mehrere Glaselemente gruppieren

Wenn du mehrere Glaselemente nebeneinander platzierst, solltest du sie in einem GlassEffectContainer gruppieren. Und das ist nicht nur eine nette Empfehlung — es ist essenziell für die korrekte Darstellung.

Warum? Liquid Glass erzeugt seinen visuellen Effekt, indem es einen Bereich größer als das Element selbst samplet und verarbeitet. Das Problem dabei: Glas kann kein anderes Glas samplen. Ohne Container würden nebeneinanderliegende Glaselemente inkonsistente visuelle Artefakte erzeugen. Nicht schön.

struct GlassToolbar: View {
    var body: some View {
        GlassEffectContainer {
            HStack(spacing: 16) {
                Button(action: {}) {
                    Image(systemName: "house.fill")
                        .frame(width: 44, height: 44)
                }
                .glassEffect(.regular.interactive(), in: .circle)

                Button(action: {}) {
                    Image(systemName: "magnifyingglass")
                        .frame(width: 44, height: 44)
                }
                .glassEffect(.regular.interactive(), in: .circle)

                Button(action: {}) {
                    Image(systemName: "person.fill")
                        .frame(width: 44, height: 44)
                }
                .glassEffect(.regular.interactive(), in: .circle)
            }
            .padding()
        }
    }
}

Spacing und Morphing

Der GlassEffectContainer akzeptiert einen optionalen spacing-Parameter. Dieser Wert bestimmt den Morphing-Schwellenwert: Wie nah müssen zwei Glaselemente sein, damit sie visuell zu einer einzigen Form verschmelzen?

// Elemente verschmelzen bei weniger als 40pt Abstand
GlassEffectContainer(spacing: 40) {
    HStack(spacing: 20) {
        // Diese Elemente werden visuell verbunden
        Text("A").padding().glassEffect()
        Text("B").padding().glassEffect()
    }
}

// Elemente bleiben getrennt
GlassEffectContainer(spacing: 8) {
    HStack(spacing: 20) {
        // Diese Elemente bleiben eigenständig
        Text("A").padding().glassEffect()
        Text("B").padding().glassEffect()
    }
}

Spiel ruhig ein bisschen mit den Werten rum — der visuelle Unterschied ist überraschend groß.

Morphing-Animationen mit glassEffectID

Eine der beeindruckendsten Funktionen von Liquid Glass sind die fließenden Morphing-Übergänge zwischen Zuständen. Dafür nutzt du glassEffectID zusammen mit dem @Namespace-Property-Wrapper:

struct MorphingDemo: View {
    @State private var istErweitert = false
    @Namespace private var namespace

    var body: some View {
        GlassEffectContainer(spacing: 40) {
            HStack(spacing: 40) {
                Button(action: {}) {
                    Image(systemName: "pencil")
                        .frame(width: 60, height: 60)
                }
                .glassEffect(.regular.interactive(), in: .circle)
                .glassEffectID("stift", in: namespace)

                if istErweitert {
                    Button(action: {}) {
                        Image(systemName: "eraser.fill")
                            .frame(width: 60, height: 60)
                    }
                    .glassEffect(.regular.interactive(), in: .circle)
                    .glassEffectID("radierer", in: namespace)

                    Button(action: {}) {
                        Image(systemName: "paintbrush.fill")
                            .frame(width: 60, height: 60)
                    }
                    .glassEffect(.regular.interactive(), in: .circle)
                    .glassEffectID("pinsel", in: namespace)
                }
            }
        }

        Button(istErweitert ? "Zuklappen" : "Aufklappen") {
            withAnimation(.spring(duration: 0.4)) {
                istErweitert.toggle()
            }
        }
        .buttonStyle(.glass)
        .padding(.top, 20)
    }
}

Durch die glassEffectID weiß SwiftUI, welche Glaselemente zusammengehören — und animiert Erscheinen, Verschwinden und Positionsänderungen als fließende Morphing-Übergänge. In der Praxis sieht das wirklich fantastisch aus, besonders bei Toolbar-Erweiterungen.

Praxisbeispiel: Floating Action Menu

So, jetzt bringen wir alles zusammen. Hier ist ein realistisches Beispiel — ein Floating Action Menu mit Liquid Glass:

struct FloatingActionMenu: View {
    @State private var istOffen = false
    @Namespace private var menuNamespace

    var body: some View {
        ZStack(alignment: .bottomTrailing) {
            // Dein Hauptinhalt
            ScrollView {
                LazyVStack(spacing: 12) {
                    ForEach(0..<20, id: \.self) { index in
                        Text("Element \(index)")
                            .frame(maxWidth: .infinity)
                            .padding()
                            .background(.regularMaterial)
                            .clipShape(RoundedRectangle(cornerRadius: 12))
                    }
                }
                .padding()
            }

            // Floating Action Menu
            VStack(alignment: .trailing, spacing: 16) {
                GlassEffectContainer(spacing: 30) {
                    VStack(alignment: .trailing, spacing: 12) {
                        if istOffen {
                            MenuButton(
                                icon: "camera.fill",
                                label: "Foto",
                                id: "foto",
                                namespace: menuNamespace
                            )
                            MenuButton(
                                icon: "doc.fill",
                                label: "Dokument",
                                id: "dokument",
                                namespace: menuNamespace
                            )
                            MenuButton(
                                icon: "link",
                                label: "Link",
                                id: "link",
                                namespace: menuNamespace
                            )
                        }

                        Button(action: {
                            withAnimation(.spring(duration: 0.35)) {
                                istOffen.toggle()
                            }
                        }) {
                            Image(systemName: istOffen ? "xmark" : "plus")
                                .font(.title2.bold())
                                .frame(width: 56, height: 56)
                                .contentTransition(.symbolEffect(.replace))
                        }
                        .glassEffect(
                            .regular.interactive().tint(.blue),
                            in: .circle
                        )
                        .glassEffectID("hauptbutton", in: menuNamespace)
                    }
                }
            }
            .padding(24)
        }
    }
}

struct MenuButton: View {
    let icon: String
    let label: String
    let id: String
    let namespace: Namespace.ID

    var body: some View {
        Button(action: { /* Aktion */ }) {
            Label(label, systemImage: icon)
                .padding(.horizontal, 16)
                .padding(.vertical, 10)
        }
        .glassEffect(.regular.interactive())
        .glassEffectID(id, in: namespace)
        .transition(.scale.combined(with: .opacity))
    }
}

Dieses Beispiel zeigt schön, wie GlassEffectContainer, interaktive Glaseffekte und Morphing-IDs zusammenspielen. Das Ergebnis ist ein flüssiges, modernes UI-Erlebnis — und deine Nutzer werden den Unterschied merken.

Migration bestehender Apps

Du fragst dich jetzt vielleicht: Muss ich meine komplette App umbauen? Die kurze Antwort: Nein. Apple hat die Migration bewusst schrittweise gestaltet — und das ist auch gut so.

Schritt 1: Kompilieren und prüfen

Kompiliere deine App mit Xcode 26 und dem iOS 26 SDK. System-Komponenten übernehmen Liquid Glass automatisch. Dann einfach visuell durchgehen und schauen, ob alles passt.

Schritt 2: Kompatibilitätsmodus bei Bedarf

Falls die automatischen Änderungen problematisch sind, kannst du über die Info.plist den Kompatibilitätsmodus aktivieren:

<key>UIDesignRequiresCompatibility</key>
<true/>

Schritt 3: Schrittweise Übernahme

Ersetze nach und nach deine bisherigen Material-Effekte durch die neuen Glass-APIs:

// Vorher (iOS 15+)
Text("Alt")
    .padding()
    .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))

// Nachher (iOS 26+)
Text("Neu")
    .padding()
    .glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))

Der Umstieg ist im Grunde unkompliziert — meistens reicht es, .background(.ultraThinMaterial, ...) durch .glassEffect() zu ersetzen.

Abwärtskompatibilität sicherstellen

Wenn deine App auch ältere iOS-Versionen unterstützen muss (was wahrscheinlich der Fall ist), nutze Verfügbarkeitsprüfungen:

if #available(iOS 26, *) {
    Text("Modern")
        .padding()
        .glassEffect(.regular, in: .rect(cornerRadius: 16))
} else {
    Text("Modern")
        .padding()
        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
}

Apple hat angekündigt, dass die vollständige Umstellung auf Liquid Glass voraussichtlich bis iOS 27 erwartet wird — du hast also noch Zeit. Aber ich würde empfehlen, jetzt schon mit der schrittweisen Migration zu beginnen.

UIKit-Integration

Falls dein Projekt UIKit verwendet oder eine hybride Architektur hat, kannst du Liquid Glass auch dort einsetzen. Apple hat UIVisualEffectView für iOS 26 aktualisiert:

// UIKit: Liquid Glass für eine View
let glassView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial))
glassView.frame = CGRect(x: 0, y: 0, width: 200, height: 60)
view.addSubview(glassView)

In einer hybriden SwiftUI/UIKit-App solltest du darauf achten, dass die Designsprache in beiden Teilen konsistent bleibt. Mein Tipp: Migriere schrittweise einzelne Screens und wiederverwendbare Komponenten, statt alles auf einmal anzufassen. So bleibst du in der Kontrolle.

Performance und Best Practices

Liquid Glass nutzt Metal und optimierte Shader für GPU-beschleunigte Echtzeit-Effekte. Auf modernen iPhones läuft das flüssig mit 120 Hz. Trotzdem gibt es ein paar Punkte, die du beachten solltest.

Do's

  • Wende .glassEffect() als letzten Modifier an — nach allen anderen Appearance-Modifiern wie .padding(), .font() oder .foregroundStyle()
  • Nutze GlassEffectContainer immer dann, wenn mehrere Glaselemente zusammen dargestellt werden
  • Halte die Anzahl der Glaselemente pro View moderat — 5–10 Elemente sind in der Regel kein Problem
  • Teste auf echten Geräten — der Simulator zeigt den Effekt, aber Performance-Messungen sind nur auf echter Hardware aussagekräftig

Don'ts

  • Kein Liquid Glass auf weißen oder sehr hellen Hintergründen — der Effekt lebt von Kontrast mit dem darunter liegenden Inhalt
  • Nicht in langen, scrollbaren Listen verwenden — jede Zelle mit Glass-Effekt belastet die GPU unnötig
  • Keinen kleinen Text in Glasflächen — die Lesbarkeit leidet trotz automatischer Farbanpassung
  • Kein Vollbild-Glass — Liquid Glass ist für die Navigationsebene gedacht, nicht für Hauptinhalte

Ein Fehler, den ich anfangs selbst gemacht habe: Glaseffekte überall einsetzen, weil sie so gut aussehen. Weniger ist hier definitiv mehr.

Barrierefreiheit

Apple hat von Anfang an Accessibility-Unterstützung in Liquid Glass integriert. Trotzdem solltest du ein paar Dinge aktiv berücksichtigen:

struct BarrierefreieGlassView: View {
    @Environment(\.accessibilityReduceTransparency) var transparenzReduziert

    var body: some View {
        Text("Zugänglich")
            .padding()
            .glassEffect(transparenzReduziert ? .identity : .regular)
    }
}

Wenn der Nutzer in den Systemeinstellungen „Transparenz reduzieren" aktiviert hat, wechselst du auf .identity — das behält das Layout bei, entfernt aber den visuellen Glaseffekt. In den meisten Fällen übernimmt das System diese Anpassung automatisch. Du musst nur eingreifen, wenn du benutzerdefinierte Glass-Elemente gebaut hast.

Achte außerdem auf ausreichenden Kontrast und teste unbedingt mit Dynamic Type in verschiedenen Größen. Glaselemente können bei größeren Schriftarten schnell überlaufen — das ist leicht zu übersehen.

Häufig gestellte Fragen

Muss ich meine App komplett umbauen, um Liquid Glass zu unterstützen?

Nein. Sobald du mit Xcode 26 kompilierst, übernehmen System-Komponenten wie NavigationBar, TabBar und Sheets den Liquid-Glass-Look automatisch. Für eigene Views kannst du schrittweise migrieren. Apple erzwingt die vollständige Übernahme voraussichtlich erst mit iOS 27.

Funktioniert Liquid Glass auch mit UIKit?

Ja. Apple hat UIVisualEffectView für iOS 26 aktualisiert, sodass auch UIKit-basierte Apps Liquid Glass nutzen können. System-Elemente übernehmen den Look automatisch. Für eigene Views brauchst du allerdings etwas mehr manuellen Aufwand als in SwiftUI.

Welche Geräte unterstützen Liquid Glass?

Liquid Glass läuft auf allen Geräten, die iOS 26 unterstützen. Die GPU-beschleunigten Effekte nutzen Metal und optimierte Shader, die auf modernen Apple-Silicon-Chips mit 120 Hz laufen. Auch ältere unterstützte Geräte zeigen den Effekt — nur gegebenenfalls mit reduzierten visuellen Details.

Was ist der Unterschied zwischen .regular, .clear und .identity?

.regular ist der Standard-Glaseffekt mit deutlicher Transparenz. .clear ist subtiler und weniger auffällig — ideal für sekundäre Elemente. .identity entfernt den visuellen Effekt komplett, behält aber das Layout bei — perfekt als Barrierefreiheits-Fallback oder für bedingte Darstellung.

Warum brauche ich einen GlassEffectContainer?

Liquid Glass erzeugt seinen Effekt, indem es einen größeren Bereich als das Element selbst samplet. Das Problem: Glas kann kein anderes Glas samplen. Ohne Container würden nebeneinanderliegende Glaselemente visuelle Artefakte zeigen. Der GlassEffectContainer ermöglicht es den Elementen, ihre Sampling-Region zu teilen, und kontrolliert zudem das Morphing-Verhalten bei Animationen.

Über den Autor Editorial Team

Our team of expert writers and editors.