Weekly Swift articles, podcasts and tips by John Sundell.

Swift clip: SwiftUI stacks and spacers

Published on 19 Feb 2020

Let’s take a look at how SwiftUI’s various stacks and spacers can be used to achieve many kinds of flexible, adaptive layouts with very little code. While SwiftUI does include several more advanced layout APIs, stacks and spacers are a great starting point for most UIs.

Sample code

A simple SwiftUI view that renders a text at the center of its parent container:

struct ContentView: View {
    var body: some View {
        Text("SwiftUI")
    }
}

Adding another text, and wrapping those two subviews within a VStack to render them on top of each other along the Y-axis:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("SwiftUI")
            Text("Layout")
        }
    }
}

Pushing our two texts to the top of the screen using a Spacer:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("SwiftUI")
            Text("Layout")
            Spacer()
        }
    }
}

Moving our texts to the top-left corner (or technically, top-leading corner), using an HStack and another Spacer:

struct ContentView: View {
    var body: some View {
        HStack {
            VStack {
                Text("SwiftUI")
                Text("Layout")
                Spacer()
            }
            Spacer()
        }
    }
}

Adding padding to our view using the .padding() modifier:

struct ContentView: View {
    var body: some View {
        HStack {
            VStack {
                Text("SwiftUI")
                Text("Layout")
                Spacer()
            }
            Spacer()
        }.padding()
    }
}

Adding an image rendered at the top-right (trailing) corner of the screen:

struct ContentView: View {
    var body: some View {
        HStack(alignment: .top) {
            VStack {
                Text("SwiftUI")
                Text("Layout")
                Spacer()
            }
            Spacer()
            Image(systemName: "star")
        }.padding()
    }
}

Extracting our current views into a new View type:

struct TopView: View {
    var body: some View {
        HStack(alignment: .top) {
            VStack {
                Text("SwiftUI")
                Text("Layout")
            }
            Spacer()
            Image(systemName: "star")
        }
    }
}

Using composition to form our content view, rather than having it contain all of our layout code:

struct ContentView: View {
    var body: some View {
        VStack {
            TopView()
            Spacer()
        }.padding()
    }
}

Adding a new layer to our view hierarchy using a ZStack:

struct ContentView: View {
    var body: some View {
        ZStack(alignment: .bottomTrailing) {
            VStack {
                TopView()
                Spacer()
            }
            Text("A new layer")
        }.padding()
    }
}