LiquidGlassReference
iOS 26 Liquid Glass: Ultimate Swift/SwiftUI Reference. This is really just a document I can point Claude at when I want to make glass. conor.fyi/writing/liquid-glass-reference
Install / Use
/learn @conorluddy/LiquidGlassReferenceQuality Score
Category
Content & MediaSupported Platforms
README
iOS 26 Liquid Glass: Comprehensive Swift/SwiftUI Reference
https://conor.fyi/writing/liquid-glass-reference
Overview
iOS 26 Liquid Glass represents Apple's most significant design evolution since iOS 7, introduced at WWDC 2025 (June 9, 2025). Liquid Glass is a translucent, dynamic material that reflects and refracts surrounding content while transforming to bring focus to user tasks. This unified design language spans iOS 26, iPadOS 26, macOS Tahoe 26, watchOS 26, tvOS 26, and visionOS 26.
Liquid Glass features real-time light bending (lensing), specular highlights responding to device motion, adaptive shadows, and interactive behaviors. The material continuously adapts to background content, light conditions, and user interactions, creating depth and hierarchy between foreground controls and background content.
Key Characteristics:
- Lensing: Bends and concentrates light in real-time (vs. traditional blur that scatters light)
- Materialization: Elements appear by gradually modulating light bending
- Fluidity: Gel-like flexibility with instant touch responsiveness
- Morphing: Dynamic transformation between control states
- Adaptivity: Multi-layer composition adjusting to content, color scheme, and size
Part 1: Foundation \u0026 Basics
1.1 Core Concepts
Design Philosophy Liquid Glass is exclusively for the navigation layer that floats above app content. Never apply to content itself (lists, tables, media). This maintains clear visual hierarchy: content remains primary while controls provide functional overlay.
Material Variants
| Variant | Use Case | Transparency | Adaptivity |
|---------|----------|--------------|------------|
| .regular | Default for most UI | Medium | Full - adapts to any content |
| .clear | Media-rich backgrounds | High | Limited - requires dimming layer |
| .identity | Conditional disable | None | N/A - no effect applied |
When to Use Each Variant:
- Regular: Toolbars, buttons, navigation bars, tab bars, standard controls
- Clear: Small floating controls over photos/maps with bold foreground content
- Identity: Conditional toggling (e.g.,
glassEffect(isEnabled ? .regular : .identity))
Design Requirements for Clear Variant (all must be met):
- Element sits over media-rich content
- Content won't be negatively affected by dimming layer
- Content above glass is bold and bright
1.2 Basic Implementation
Simple Glass Effect
import SwiftUI
struct BasicGlassView: View {
var body: some View {
Text("Hello, Liquid Glass!")
.padding()
.glassEffect() // Default: .regular variant, .capsule shape
}
}
With Explicit Parameters
Text("Custom Glass")
.padding()
.glassEffect(.regular, in: .capsule, isEnabled: true)
API Signature
func glassEffect<S: Shape>(
_ glass: Glass = .regular,
in shape: S = DefaultGlassEffectShape,
isEnabled: Bool = true
) -> some View
1.3 Glass Type Modifiers
Core Structure
struct Glass {
static var regular: Glass
static var clear: Glass
static var identity: Glass
func tint(_ color: Color) -> Glass
func interactive() -> Glass
}
Tinting
// Basic tint
Text("Tinted")
.padding()
.glassEffect(.regular.tint(.blue))
// With opacity
Text("Subtle Tint")
.padding()
.glassEffect(.regular.tint(.purple.opacity(0.6)))
Purpose: Convey semantic meaning (primary action, state), NOT decoration. Use selectively for call-to-action only.
Interactive Modifier (iOS only)
Button("Tap Me") {
// action
}
.glassEffect(.regular.interactive())
Behaviors Enabled:
- Scaling on press
- Bouncing animation
- Shimmering effect
- Touch-point illumination that radiates to nearby glass
- Response to tap and drag gestures
Method Chaining
.glassEffect(.regular.tint(.orange).interactive())
.glassEffect(.clear.interactive().tint(.blue)) // Order doesn't matter
1.4 Custom Shapes
Available Shapes
// Capsule (default)
.glassEffect(.regular, in: .capsule)
// Circle
.glassEffect(.regular, in: .circle)
// Rounded Rectangle
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
// Container-concentric (aligns with container corners)
.glassEffect(.regular, in: .rect(cornerRadius: .containerConcentric))
// Ellipse
.glassEffect(.regular, in: .ellipse)
// Custom shape conforming to Shape protocol
struct CustomShape: Shape {
func path(in rect: CGRect) -> Path {
// Custom path logic
}
}
.glassEffect(.regular, in: CustomShape())
Corner Concentricity Maintains perfect alignment between elements and containers across devices:
// Automatically matches container/window corners
RoundedRectangle(cornerRadius: .containerConcentric, style: .continuous)
1.5 Text \u0026 Icons with Glass
Text Rendering
Text("Glass Text")
.font(.title)
.bold()
.foregroundStyle(.white) // High contrast for legibility
.padding()
.glassEffect()
Text on glass automatically receives vibrant treatment - adjusts color, brightness, saturation based on background.
Icon Rendering
Image(systemName: "heart.fill")
.font(.largeTitle)
.foregroundStyle(.white)
.frame(width: 60, height: 60)
.glassEffect(.regular.interactive())
Labels
Label("Settings", systemImage: "gear")
.labelStyle(.iconOnly)
.padding()
.glassEffect()
1.6 Accessibility Support
Automatic Adaptation - No code changes required:
- Reduced Transparency: Increases frosting for clarity
- Increased Contrast: Stark colors and borders
- Reduced Motion: Tones down animations and elastic effects
- iOS 26.1+ Tinted Mode: User-controlled opacity increase (Settings → Display & Brightness → Liquid Glass)
Environment Values
@Environment(\.accessibilityReduceTransparency) var reduceTransparency
@Environment(\.accessibilityReduceMotion) var reduceMotion
var body: some View {
Text("Accessible")
.padding()
.glassEffect(reduceTransparency ? .identity : .regular)
}
Best Practice: Let system handle accessibility automatically. Don't override unless absolutely necessary.
Part 2: Intermediate Techniques
2.1 GlassEffectContainer
Purpose
- Combines multiple Liquid Glass shapes into unified composition
- Improves rendering performance by sharing sampling region
- Enables morphing transitions between glass elements
- Critical Rule: Glass cannot sample other glass; container provides shared sampling region
Basic Usage
GlassEffectContainer {
HStack(spacing: 20) {
Image(systemName: "pencil")
.frame(width: 44, height: 44)
.glassEffect(.regular.interactive())
Image(systemName: "eraser")
.frame(width: 44, height: 44)
.glassEffect(.regular.interactive())
}
}
With Spacing Control
GlassEffectContainer(spacing: 40.0) {
// Glass elements within 40 points will morph together
ForEach(icons) { icon in
IconView(icon)
.glassEffect()
}
}
Spacing Parameter: Controls morphing threshold - elements within this distance visually blend and morph together during transitions.
API Signature
struct GlassEffectContainer<Content: View>: View {
init(spacing: CGFloat? = nil, @ViewBuilder content: () -> Content)
init(@ViewBuilder content: () -> Content)
}
2.2 Morphing Transitions with glassEffectID
Requirements for Morphing:
- Elements in same
GlassEffectContainer - Each view has
glassEffectIDwith shared namespace - Views conditionally shown/hidden trigger morphing
- Animation applied to state changes
Basic Morphing Setup
struct MorphingExample: View {
@State private var isExpanded = false
@Namespace private var namespace
var body: some View {
GlassEffectContainer(spacing: 30) {
Button(isExpanded ? "Collapse" : "Expand") {
withAnimation(.bouncy) {
isExpanded.toggle()
}
}
.glassEffect()
.glassEffectID("toggle", in: namespace)
if isExpanded {
Button("Action 1") { }
.glassEffect()
.glassEffectID("action1", in: namespace)
Button("Action 2") { }
.glassEffect()
.glassEffectID("action2", in: namespace)
}
}
}
}
API Signature
func glassEffectID<ID: Hashable>(
_ id: ID,
in namespace: Namespace.ID
) -> some View
Advanced Morphing Pattern - Expandable Action Menu
struct ActionButtonsView: View {
@State private var showActions = false
@Namespace private var namespace
var body: some View {
ZStack {
Image("background")
.resizable()
.ignoresSafeArea()
GlassEffectContainer(spacing: 30) {
VStack(spacing: 30) {
// Top button
if showActions {
actionButton("rotate.right")
.glassEffectID("rotate", in: namespace)
}
HStack(spacing: 30) {
// Left button
if showActions {
actionButton("circle.lefthalf.filled")
.glassEffectID("contrast", in: namespace)
}
// Toggle (always visible
Security Score
Audited on Mar 31, 2026
