| name | ios26-liquid-glass |
| description | iOS 26 Liquid Glass API reference for SwiftUI and UIKit. Use this skill when working with glassEffect, GlassEffectContainer, glassEffectID, glassEffectUnion, or any Liquid Glass related code on iOS 26+. |
iOS 26 Liquid Glass Reference
Liquid Glass is Apple's design language introduced at WWDC 2025. Glass elements float above content with translucent, depth-aware surfaces that reflect and refract surrounding content.
SwiftUI - glassEffect Modifier
func glassEffect<S: Shape>(
_ glass: Glass = .regular,
in shape: S = DefaultGlassEffectShape,
isEnabled: Bool = true
) -> some View
Apply .glassEffect() last in your modifier chain for correct rendering.
Glass Variants
| Variant | Description | Use Case |
|---|---|---|
.regular |
Default, balanced transparency | Most UI elements (buttons, controls, overlays) |
.clear |
High transparency, limited adaptivity | Media-rich backgrounds (needs dimming layer) |
.identity |
No effect applied | Conditional glass application |
Glass Modifiers
// semantic color tinting - use only for meaning (success, warning, destructive)
.glassEffect(.regular.tint(.blue))
// iOS-only: enables scaling, bounce, shimmer on interaction
.glassEffect(.regular.interactive())
// combined
.glassEffect(.regular.tint(.blue).interactive())
Shapes
// default shape (capsule)
.glassEffect()
.glassEffect(.regular, in: DefaultGlassEffectShape())
// built-in shapes
.glassEffect(.regular, in: .capsule)
.glassEffect(.regular, in: .circle)
.glassEffect(.regular, in: .ellipse)
.glassEffect(.regular, in: .rect(cornerRadius: 12))
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
// adapts corner radius to parent container (for buttons in cards/sheets)
.glassEffect(.regular, in: .rect(cornerRadius: .containerConcentric))
GlassEffectContainer
Groups multiple glass elements for seamless blending and morphing. Glass cannot sample other glass, so use this when elements are positioned closely.
GlassEffectContainer(spacing: 8) { // spacing = merge threshold in points
Button("One") { }
.glassEffect()
Button("Two") { }
.glassEffect()
}
When elements are closer than spacing, they visually blend and morph together like water droplets.
Rules
- Don't nest
GlassEffectContainerinside another - Don't place
MenuinsideGlassEffectContainer(breaks morphing in iOS 26.1) - Don't use
.clipShape()on glassEffect views
glassEffectID - Morphing Transitions
Associates glass elements across states for fluid morphing animations. Requires @Namespace and GlassEffectContainer.
@Namespace var namespace
@State var expanded = false
GlassEffectContainer {
if expanded {
HStack {
Button("Home") { }
.glassEffect(.regular.interactive())
.glassEffectID("home", in: namespace)
Button("Settings") { }
.glassEffect(.regular.interactive())
.glassEffectID("settings", in: namespace)
}
} else {
Button("Menu") { expanded = true }
.glassEffect(.regular.interactive())
.glassEffectID("menu", in: namespace)
}
}
.animation(.easeInOut, value: expanded)
Requirements for Morphing
- Elements must be within the same
GlassEffectContainer - Each view needs
glassEffectIDwith shared namespace - Views must be conditionally shown/hidden
- Animation must be applied to the state change
- All morphing elements should use same Glass style and tint
glassEffectUnion - Grouping Elements
Makes multiple elements appear as a single glass shape (like Apple Maps zoom controls).
@Namespace var ns
VStack(spacing: 0) {
Button(action: { /* zoom in */ }) {
Image(systemName: "plus")
}
.glassEffect(.regular.tint(.white.opacity(0.8)))
.glassEffectUnion(id: "zoom", namespace: ns)
Divider()
Button(action: { /* zoom out */ }) {
Image(systemName: "minus")
}
.glassEffect(.regular.tint(.white.opacity(0.8)))
.glassEffectUnion(id: "zoom", namespace: ns)
}
Requirements
All elements in a union must have:
- Same union id
- Same glass effect variant
- Same tint (color and opacity)
UIKit Support
UIGlassEffect
if #available(iOS 26.0, *) {
let glassEffect = UIGlassEffect()
let effectView = UIVisualEffectView(effect: glassEffect)
effectView.frame = CGRect(x: 20, y: 100, width: 200, height: 50)
view.addSubview(effectView)
// add content to contentView
let label = UILabel()
label.text = "Glass Effect"
effectView.contentView.addSubview(label)
}
UIGlassContainerEffect - Merging Glass Views
if #available(iOS 26.0, *) {
let containerEffect = UIGlassContainerEffect()
containerEffect.spacing = 12 // merge distance threshold
let containerView = UIVisualEffectView(effect: containerEffect)
let glass1 = UIVisualEffectView(effect: UIGlassEffect())
let glass2 = UIVisualEffectView(effect: UIGlassEffect())
containerView.contentView.addSubview(glass1)
containerView.contentView.addSubview(glass2)
}
Corner Configuration
if #available(iOS 26.0, *) {
let effectView = UIVisualEffectView(effect: UIGlassEffect())
effectView.cornerConfiguration = UIViewCornerConfiguration(
corners: .allCorners,
cornerRadius: 16
)
}
UIHostingController Integration
When embedding SwiftUI glass in UIKit:
- Place in
navigationItem.titleView(notleftBarButtonItem/rightBarButtonItem) - Set
sizingOptions = [.intrinsicContentSize]
Backward Compatibility
The Glass type only exists on iOS 26+. Create wrappers with #available:
extension View {
@ViewBuilder
func applyGlassEffect() -> some View {
if #available(iOS 26.0, *) {
self.glassEffect()
} else {
self // no-op on older iOS
}
}
// with parameters - requires @available at call site
@available(iOS 26.0, *)
@ViewBuilder
func applyGlassEffect(
_ glass: Glass,
in shape: some Shape = DefaultGlassEffectShape()
) -> some View {
self.glassEffect(glass, in: shape)
}
}
Fallback for older iOS
if #available(iOS 26.0, *) {
content.glassEffect()
} else {
content.background(.ultraThinMaterial, in: .capsule)
}
Design Guidelines
When to Use
- Navigation elements (tab bars, toolbars, nav bars)
- Floating action buttons
- Control panels and overlays
- Search bars and input fields
- Modal/sheet presentations
- Interactive elements that sit "above" content
Design System Consistency
Liquid Glass should complement, not replace, standard iOS design patterns. Use it strategically to enhance the user experience while maintaining familiarity with platform conventions.
When NOT to Use
- Core content (list rows, table cells)
- Card backgrounds with primary information
- Media-rich content areas
- Text-heavy sections
- Decorative elements with no function
- Settings and configuration screens
- Form-based interfaces (use standard Form styling)
- Administrative/account management views
- Data entry and profile editing screens
- Any screen requiring standard iOS accessibility patterns
Best Practices
- Use
.interactive()for buttons/controls on iOS - Use
.tint()only for semantic meaning - Test in light mode, dark mode, and with "Reduce Transparency"
- Maintain 4.5:1 contrast ratio (WCAG AA)
- Use
.containerConcentriccorner radius for elements in containers - Monitor performance in scrollable lists on older iPhones
- Prefer standard
FormandListcomponents for settings and data entry - Use liquid glass sparingly - reserve for navigation, floating elements, and interactive components
- Maintain consistency with platform conventions (Form for settings, standard buttons for actions)
Known Issues
| Issue | Workaround |
|---|---|
Menu in GlassEffectContainer breaks morphing (iOS 26.1) |
Don't nest Menu in container |
| Morphing circle ↔ rectangle has glitches | Avoid drastically different shape transitions |
glassEffectID inconsistent |
Consider .matchedGeometryEffect as alternative |
| UIHostingController in bar items causes side effects | Use titleView instead |
Button Styles
// translucent glass button
Button("Glass") { }
.buttonStyle(.glass)
// opaque prominent glass button
Button("Prominent") { }
.buttonStyle(.glassProminent)
Tab Bar Behavior
// tab bar minimizes when scrolling down
.tabBarMinimizeBehavior(.onScrollDown)