← All courses

Views, Modifiers & Composition

🗓 May 31, 2026 ⏱ 2 min read

Composition: build big from small

The SwiftUI way is to break a screen into many tiny views, each doing one thing, then combine them. This keeps each piece simple, reusable and previewable.

struct ProfileHeader: View {
    let name: String
    let role: String
    var body: some View {
        VStack(alignment: .leading) {
            Text(name).font(.title2).bold()
            Text(role).font(.subheadline).foregroundStyle(.secondary)
        }
    }
}

struct ProfileScreen: View {
    var body: some View {
        VStack(spacing: 16) {
            ProfileHeader(name: "Anand Gaur", role: "iOS Developer")
            // more small views...
        }
        .padding()
    }
}

What modifiers really are

A modifier doesn’t change a view in place; it wraps the view and returns a new one. That’s why you chain them. Because each modifier returns a new view, the order you apply them in matters.

Text("Hello")
    .padding()                      // space around the text
    .background(.purple)            // color fills including that padding
    .foregroundStyle(.white)
    .clipShape(RoundedRectangle(cornerRadius: 12))

Order matters — a concrete example

// padding THEN background -> padding is inside the colored box
Text("A").padding().background(.purple)

// background THEN padding -> color first, padding pushes outward
Text("B").background(.purple).padding()

Read a modifier chain top to bottom as a sequence of wrapping steps. When a view looks wrong, the order of modifiers is the first thing to check.

Common useful modifiers

  • .font(), .foregroundStyle(), .bold() — text styling.
  • .padding(), .frame(width:height:) — size and spacing.
  • .background(), .cornerRadius(), .shadow() — appearance.
  • .onTapGesture { } — interaction.

Reusable styling with custom views and ViewModifiers

If you repeat the same styling, extract it. You can make a small view, or a custom ViewModifier:

struct CardStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color(.systemGray6))
            .clipShape(RoundedRectangle(cornerRadius: 16))
    }
}

extension View {
    func cardStyle() -> some View { modifier(CardStyle()) }
}

// usage
Text("Reusable card").cardStyle()

Common mistakes

  • Getting padding/background order wrong (the classic confusion).
  • Building one giant body instead of small composable views.
  • Copy-pasting the same modifier chain instead of extracting a reusable style.
Summary: Compose UI from small views and style them with chained modifiers — remembering that each modifier wraps the previous result, so order matters. Extract repeated styling into custom views or ViewModifiers.