- Published on
> Add Spacing to Toolbars with ToolbarSpacer in SwiftUI
- Authors

- Name
- Mick MacCallum
- @0x7fs
iOS 26 introduced ToolbarSpacer, a dedicated API for adding spacing between toolbar items. Before iOS 26, controlling spacing required workarounds using ToolbarItemGroup and regular Spacer() views. Now you have a clean, purpose-built solution with both fixed and flexible spacing options.
Basic Usage
Place ToolbarSpacer between toolbar items to add space:
struct ContentView: View {
var body: some View {
NavigationStack {
Text("Content")
.toolbar {
ToolbarItem {
Button("Delete", systemImage: "trash", role: .destructive) { }
}
ToolbarSpacer(.fixed)
ToolbarItem {
Button("Add", systemImage: "plus") { }
}
}
}
}
}
This creates a fixed amount of space between the Delete and Add buttons.
Fixed vs Flexible Spacing
ToolbarSpacer supports two spacing modes:
Fixed Spacing
Fixed spacing adds a consistent, system-defined gap between items:
.toolbar {
ToolbarItem { Button("First", systemImage: "1.circle") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("Second", systemImage: "2.circle") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("Third", systemImage: "3.circle") { } }
}
Use fixed spacing for:
- Consistent separation between related items
- Visual grouping
- Predictable layout
Flexible Spacing
Flexible spacing expands to fill available space, pushing items apart:
.toolbar {
ToolbarItem { Button("Left", systemImage: "arrow.left") { } }
ToolbarSpacer(.flexible)
ToolbarItem { Button("Right", systemImage: "arrow.right") { } }
}
Use flexible spacing for:
- Items at opposite ends of the toolbar
- Maximum separation between groups
- Dynamic spacing that adapts to available space
Combining Multiple Spacers
Create sophisticated layouts by combining spacers:
.toolbar {
ToolbarItem { Button("Action 1", systemImage: "1.circle") { } }
ToolbarItem { Button("Action 2", systemImage: "2.circle") { } }
ToolbarSpacer(.flexible)
ToolbarItem { Button("Action 3", systemImage: "3.circle") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("Action 4", systemImage: "4.circle") { } }
}
This groups Action 1 and 2 on the left, then uses flexible spacing to push Action 3 and 4 to the right with fixed spacing between them.
Targeting Specific Placements
Specify placement for spacers in specific toolbar regions:
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Leading", systemImage: "arrow.left") { }
}
ToolbarSpacer(.fixed, placement: .topBarLeading)
ToolbarItem(placement: .topBarLeading) {
Button("Also Leading", systemImage: "star") { }
}
ToolbarItem(placement: .topBarTrailing) {
Button("Trailing", systemImage: "arrow.right") { }
}
}
Practical Example: Document Editor
Here's a toolbar with multiple action groups:
struct DocumentEditor: View {
var body: some View {
NavigationStack {
TextEditor(text: .constant("Document content"))
.navigationTitle("Document")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel", systemImage: "xmark") { }
}
ToolbarItemGroup(placement: .primaryAction) {
Button("Bold", systemImage: "bold") { }
Button("Italic", systemImage: "italic") { }
Button("Underline", systemImage: "underline") { }
ToolbarSpacer(.fixed)
Button("Link", systemImage: "link") { }
}
}
}
}
}
Bottom Toolbar Example
ToolbarSpacer works in bottom toolbars too:
struct PhotoEditor: View {
var body: some View {
NavigationStack {
Image(systemName: "photo")
.resizable()
.scaledToFit()
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Button("Rotate", systemImage: "rotate.right") { }
Button("Crop", systemImage: "crop") { }
ToolbarSpacer(.flexible)
Button("Filters", systemImage: "camera.filters") { }
ToolbarSpacer(.flexible)
Button("Adjust", systemImage: "slider.horizontal.3") { }
}
}
}
}
}
Comparing with Pre-iOS 26 Approaches
Before iOS 26, you had to use workarounds:
// Before iOS 26
.toolbar {
ToolbarItemGroup(placement: .topBarTrailing) {
Button("First") { }
Spacer()
Button("Second") { }
}
}
// iOS 26+
.toolbar {
ToolbarItem { Button("First") { } }
ToolbarSpacer(.flexible)
ToolbarItem { Button("Second") { } }
}
The new approach is cleaner and more explicit.
Best Practices
Use Fixed for Grouping
Visually group related items with fixed spacing:
.toolbar {
// Text formatting group
ToolbarItem { Button("Bold") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("Italic") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("Underline") { } }
ToolbarSpacer(.flexible)
// Alignment group
ToolbarItem { Button("Left") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("Center") { } }
}
Use Flexible for Balance
Create balanced, symmetrical layouts:
.toolbar {
ToolbarItem { Button("Left") { } }
ToolbarSpacer(.flexible)
ToolbarItem { Button("Center") { } }
ToolbarSpacer(.flexible)
ToolbarItem { Button("Right") { } }
}
Consider Touch Targets
Ensure adequate spacing for comfortable tapping:
// Good: Fixed spacing ensures minimum separation
.toolbar {
ToolbarItem { Button("A") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("B") { } }
}
Maintain Visual Hierarchy
Use spacing to communicate importance:
.toolbar {
ToolbarItem { Button("Save") { } }
ToolbarSpacer(.fixed)
ToolbarItem { Button("Share") { } }
ToolbarSpacer(.flexible)
ToolbarItem { Button("Delete", role: .destructive) { } }
}
Working with ToolbarItemGroup
ToolbarSpacer works seamlessly with ToolbarItemGroup:
.toolbar {
ToolbarItemGroup(placement: .topBarTrailing) {
Button("Edit", systemImage: "pencil") { }
Button("Copy", systemImage: "doc.on.doc") { }
ToolbarSpacer(.fixed)
Button("Share", systemImage: "square.and.arrow.up") { }
ToolbarSpacer(.flexible)
Button("More", systemImage: "ellipsis") { }
}
}
// Continue_Learning
How to Change the Background Color of a View in SwiftUI
Learn different ways to set background colors on SwiftUI views, from simple color fills to gradients and materials.
How to Round Specific Corners of a View in SwiftUI
Learn how to round only certain corners of a SwiftUI view using UnevenRoundedRectangle, custom shapes, and clipShape.
How to Resize an Image in SwiftUI
Learn how to resize images in SwiftUI using resizable(), frame(), and different content modes like scaledToFit and scaledToFill.
// Stay Updated
Get notified when I publish new tutorials on Swift, SwiftUI, and iOS development. No spam, unsubscribe anytime.