- Published on
> Coordinating Glass Elements with GlassEffectContainer
- Authors

- Name
- Mick MacCallum
- @0x7fs
Placing multiple .glassEffect() views next to each other can produce unexpected results. Glass can't sample other glass, so overlapping glass elements may not blend correctly. SwiftUI solves this with GlassEffectContainer, a container view that coordinates how glass elements render together.
The Problem
When glass elements are close together or overlap without a container, each one renders independently. They don't blend at their edges, and you may see harsh seams or inconsistent lighting:
// Without a container, these render independently
HStack(spacing: 8) {
Button("Home") { }
.padding()
.glassEffect()
Button("Search") { }
.padding()
.glassEffect()
Button("Profile") { }
.padding()
.glassEffect()
}
Using GlassEffectContainer
Wrap your glass elements in a GlassEffectContainer to get proper blending:
import SwiftUI
struct GlassToolbar: View {
var body: some View {
GlassEffectContainer {
HStack(spacing: 8) {
Button("Home") { }
.padding()
.glassEffect()
Button("Search") { }
.padding()
.glassEffect()
Button("Profile") { }
.padding()
.glassEffect()
}
}
}
}
Now the system treats these as a coordinated group. The glass surfaces blend smoothly at their edges, share consistent blur and lighting, and render more efficiently.
Controlling Blend Distance with Spacing
The spacing parameter tells the container how close elements need to be before they visually merge:
// Elements within 30 points will blend together
GlassEffectContainer(spacing: 30) {
HStack(spacing: 20) {
Button("Edit") { }
.padding()
.glassEffect()
Button("Share") { }
.padding()
.glassEffect()
}
}
With spacing: 30 and an HStack spacing of 20 points, the buttons are close enough to merge into a unified glass shape. If you increased the HStack spacing beyond 30 points, they'd remain separate.
The spacing parameter is especially useful when you want glass elements that are conceptually grouped to visually connect, while keeping other elements distinct:
GlassEffectContainer(spacing: 40) {
VStack(spacing: 60) {
// These two will stay separate (60 > 40)
HStack(spacing: 16) {
// But these will blend (16 < 40)
iconButton("house.fill")
iconButton("magnifyingglass")
iconButton("person.fill")
}
HStack(spacing: 16) {
iconButton("gear")
iconButton("info.circle")
}
}
}
Building a Floating Action Menu
Here's a practical example showing a floating action button that expands to reveal options:
import SwiftUI
struct FloatingActionMenu: View {
@State private var isExpanded = false
var body: some View {
ZStack(alignment: .bottomTrailing) {
Color.blue.gradient
.ignoresSafeArea()
GlassEffectContainer(spacing: 20) {
VStack(spacing: 12) {
if isExpanded {
actionButton(icon: "camera.fill", label: "Camera")
actionButton(icon: "photo.fill", label: "Photos")
actionButton(icon: "doc.fill", label: "Files")
}
Button {
withAnimation(.bouncy) {
isExpanded.toggle()
}
} label: {
Image(systemName: isExpanded ? "xmark" : "plus")
.font(.title2)
.fontWeight(.semibold)
.foregroundStyle(.white)
.frame(width: 56, height: 56)
}
.glassEffect(.regular.tint(.blue), in: .circle)
}
}
.padding()
}
}
func actionButton(icon: String, label: String) -> some View {
Button {
// action
} label: {
Label(label, systemImage: icon)
.foregroundStyle(.white)
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
.glassEffect()
}
}
When the menu expands, the buttons appear within the same glass container. Because their spacing (12 points) is less than the container's spacing threshold (20 points), they blend together into a cohesive glass surface as they animate in.
Nested Containers
You can nest GlassEffectContainer views when you need different spacing behavior in different areas:
GlassEffectContainer(spacing: 50) {
VStack(spacing: 40) {
// This inner container has its own spacing rules
GlassEffectContainer(spacing: 16) {
HStack(spacing: 8) {
Button("A") { }.padding().glassEffect()
Button("B") { }.padding().glassEffect()
}
}
// This group uses the outer container's spacing
HStack(spacing: 8) {
Button("X") { }.padding().glassEffect()
Button("Y") { }.padding().glassEffect()
}
}
}
The inner container creates a tightly-coupled group, while the outer container governs how those groups relate to each other.
Performance Considerations
GlassEffectContainer isn't just about visual consistency. Grouping glass elements improves rendering performance because the system can composite them together rather than processing each independently. For interfaces with several glass elements, always use a container.
That said, don't wrap your entire app in one giant container. Keep containers scoped to logically related groups of glass elements. A toolbar's buttons belong in one container; a separate floating action button can have its own.
Tips for Layout
When building layouts inside a container, keep the spacing values consistent. If your HStack uses 12-point spacing, set the container's spacing to at least 12 if you want blending, or higher if you want separation. Mismatched values can lead to unexpected results where some elements blend and others don't.
For buttons that should clearly appear as one unified control, use tight spacing. For elements that are related but distinct, increase the layout spacing beyond the container threshold.
Once you have your containers set up, you can add glassEffectID to individual elements to enable smooth morphing animations between different UI states.
// Continue_Learning
Building Interactive Glass Controls in SwiftUI
Make your glass elements respond to touch with scaling, shimmer effects, and touch-point illumination using the interactive() modifier and glass button styles.
Getting Started with Liquid Glass in SwiftUI
iOS 26 introduces Liquid Glass, a translucent design language for navigation elements. Here's how to apply the glassEffect modifier to your custom views.
Creating Morphing Glass Transitions with glassEffectID
The glassEffectID modifier enables glass views to smoothly morph into one another during state changes, creating fluid transitions that feel native to iOS 26.
// Stay Updated
Get notified when I publish new tutorials on Swift, SwiftUI, and iOS development. No spam, unsubscribe anytime.