- Published on
> Centering Views in SwiftUI
- Authors

- Name
- Mick MacCallum
- @0x7fs
One of the most common frustrations when starting with SwiftUI is getting views to center the way you expect. You add a VStack, throw in some content, and wonder why it's sitting at the top of the screen instead of the middle. Or you try to center something horizontally and it stubbornly hugs the leading edge. The confusion usually comes from mixing up two different concepts: how views align within a stack versus how a view positions itself within available space.
The Two Types of Alignment
SwiftUI has two distinct alignment mechanisms that serve different purposes, and understanding the difference unlocks most layout puzzles.
Stack alignment controls how sibling views line up relative to each other. When you write VStack(alignment: .center), you're telling the stack to center its children horizontally relative to one another—but the stack itself still sizes to fit its content and positions itself according to its parent.
Frame alignment controls how a view positions itself within the space it's given. When you apply .frame(maxWidth: .infinity, alignment: .center), you're telling the view to expand and then place its content in the center of that expanded space.
Here's the key insight: a VStack with centered alignment doesn't center itself on screen. It centers its children relative to each other, then takes up only as much space as it needs.
Centering a View on Screen
To center a view both horizontally and vertically, you need to give it space to center within. The most straightforward approach uses Spacer views:
var body: some View {
VStack {
Spacer()
Text("Centered")
Spacer()
}
.frame(maxWidth: .infinity)
}
The vertical Spacer views push the content to the middle, and maxWidth: .infinity ensures the stack expands horizontally. Alternatively, you can use frame alignment directly:
var body: some View {
Text("Centered")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
This works because frame defaults to center alignment. The text expands to fill available space, then positions itself in the center.
When Stack Alignment Isn't Enough
Consider this example where you want a label and value to be centered on screen, but left-aligned relative to each other:
var body: some View {
VStack(alignment: .leading) {
Text("Username")
.font(.caption)
.foregroundStyle(.secondary)
Text("john_appleseed")
.font(.title2)
}
}
The text aligns correctly (caption above the username, both left-aligned), but the whole block sits at the top-leading corner. To center this block on screen while preserving internal alignment:
var body: some View {
VStack(alignment: .leading) {
Text("Username")
.font(.caption)
.foregroundStyle(.secondary)
Text("john_appleseed")
.font(.title2)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
Now the VStack expands to fill available space and centers its content (the left-aligned text block) within that space.
Horizontal Centering in HStacks
The same principle applies horizontally. An HStack with center alignment centers its children vertically relative to each other—it doesn't center them horizontally within the parent.
To push content to the center of an HStack:
HStack {
Spacer()
Text("Centered")
Spacer()
}
Or to center one element while keeping another at the edge, use a ZStack or overlay approach:
HStack {
Button("Back") { }
Spacer()
Text("Title")
Spacer()
Button("Back") { }
.hidden() // Balances the layout
}
GeometryReader for Precise Positioning
When you need exact positioning relative to the screen or parent, GeometryReader provides the dimensions you need:
GeometryReader { geometry in
Text("Centered")
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
}
Use this sparingly—SwiftUI's layout system handles most cases more elegantly. But for custom positioning or animations, GeometryReader gives you the control you need.
Common Mistakes
The most frequent issue is expecting a stack to expand automatically. Stacks are "hugging" by default—they shrink to fit their content. If you want a stack to fill available space, you must explicitly tell it to with .frame(maxWidth: .infinity) or similar.
Another common mistake is applying frame alignment without expanding the frame first. Writing .frame(alignment: .center) without specifying a size does nothing, because the frame matches the content size and there's no extra space to align within.
Summary
When centering isn't working as expected, ask yourself: "Am I trying to align siblings relative to each other, or position something within available space?" Stack alignment handles the first case. Frame modifiers with maxWidth/maxHeight handle the second. Once that distinction clicks, SwiftUI's layout system becomes much more predictable.
// Continue_Learning
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.
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 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.
// Stay Updated
Get notified when I publish new tutorials on Swift, SwiftUI, and iOS development. No spam, unsubscribe anytime.