SwiftUI Basics: Building Your First View with `Text`, `Image`, and `VStack`


When Pixar builds a scene in Finding Nemo, every visual element — the ocean, the fish, the light rays — is placed deliberately on screen. SwiftUI works the same way: every piece of your app’s interface is a view that you declare in code, and SwiftUI handles drawing it on screen.

This guide covers how to create views with Text and Image, stack them together with VStack, HStack, and ZStack, and customize their appearance with modifiers. We won’t cover layout sizing or state management — those have their own dedicated posts.

This post assumes you are comfortable with Xcode and understand the basics of structs and classes.

What You’ll Learn

What Is a View?

A view is anything you can see on screen — a piece of text, an image, a button, or an entire screen layout. In SwiftUI, views are lightweight Swift structs that conform to the View protocol.

Apple Docs: View — SwiftUI

Think of views like the storyboard panels in a Pixar movie. Each panel describes what should appear in that frame. You don’t draw pixels by hand — you describe what you want, and the rendering engine (SwiftUI) figures out how to display it.

Every SwiftUI view has a body property that returns the content to display:

struct MoviePosterView: View {
    var body: some View {
        Text("Toy Story")
    }
}
Toy Story

The some View return type means “this property returns something that conforms to View, but we don’t need to specify the exact type.” SwiftUI figures that out for you.

Creating Text Views

The most basic view is Text. It displays a string on screen, similar to a title card in a movie.

Apple Docs: Text — SwiftUI

Text("To infinity and beyond!")
To infinity and beyond!

You can change how text looks by chaining modifiers — methods that return a new, modified version of the view:

Text("Buzz Lightyear")
    .font(.title)
    .foregroundStyle(.blue)
    .bold()
Buzz Lightyear
(displayed in large, bold, blue text)

Each modifier transforms the text step by step: .font(.title) makes it larger, .foregroundStyle(.blue) changes the color, and .bold() makes it heavier.

You can also display multi-line text. SwiftUI wraps text automatically when it reaches the edge of the screen:

Text("A toy's life is only worth living if you're being loved by a kid.")
    .font(.body)
    .multilineTextAlignment(.center)

Adding Images

Images bring your interface to life. SwiftUI provides two main ways to display images.

Apple Docs: Image — SwiftUI

System Images (SF Symbols)

Apple includes thousands of built-in icons called SF Symbols. You reference them by name:

Image(systemName: "star.fill")
    .font(.largeTitle)
    .foregroundStyle(.yellow)
★ (a large yellow star icon)

The systemName parameter tells SwiftUI to look up an icon from the SF Symbols library instead of your project’s assets.

Custom Images (Asset Catalog)

To use your own images, add them to the Asset Catalog in Xcode (the Assets.xcassets folder) and reference them by name:

Image("woody-poster")
    .resizable()
    .scaledToFit()
    .frame(width: 200, height: 300)

The .resizable() modifier is required for custom images — without it, the image displays at its original pixel size, which is often too large. The .scaledToFit() modifier ensures the image scales proportionally to fit within the frame.

Stacking Views Together

A single text or image is rarely enough. You combine views by placing them inside stacks — containers that arrange their children in a line or on top of each other.

VStack — Vertical Stack

Apple Docs: VStack — SwiftUI

A VStack arranges views from top to bottom, like movie credits scrolling down the screen:

VStack {
    Text("WALL-E")
        .font(.title)
    Text("Directed by Andrew Stanton")
        .font(.subheadline)
    Image(systemName: "film")
        .font(.largeTitle)
}
WALL-E
Directed by Andrew Stanton
🎞 (film icon)
(all stacked vertically, centered)

HStack — Horizontal Stack

Apple Docs: HStack — SwiftUI

An HStack arranges views from left to right, like characters standing side by side in a scene:

HStack {
    Image(systemName: "star.fill")
        .foregroundStyle(.yellow)
    Text("5 Stars")
    Text("·")
    Text("Pixar")
}
★ 5 Stars · Pixar
(all arranged in a single horizontal line)

ZStack — Depth Stack

Apple Docs: ZStack — SwiftUI

A ZStack layers views on top of each other, like animation cels stacked on a light table. The first view is at the back, and the last view is at the front:

ZStack {
    Color.blue
    Text("Finding Nemo")
        .font(.largeTitle)
        .foregroundStyle(.white)
}
Finding Nemo
(white text centered on a blue background)

Nesting Stacks

The real power comes from nesting stacks inside each other. Here is a simple movie card:

VStack(alignment: .leading) {
    Text("Ratatouille")
        .font(.headline)
    HStack {
        Image(systemName: "star.fill")
            .foregroundStyle(.yellow)
        Text("4.8")
        Text("·")
        Text("2007")
            .foregroundStyle(.secondary)
    }
}
Ratatouille
★ 4.8 · 2007

The outer VStack stacks the title above the details, while the inner HStack lays the rating, separator, and year in a horizontal row.

Applying Modifiers

Modifiers are methods you call on a view to change its appearance or behavior. Every modifier returns a new view, so you can chain them together.

Apple Docs: ViewModifier — SwiftUI

Modifier Order Matters

Modifiers apply from top to bottom. The order changes the result:

// Padding THEN background
Text("Monsters, Inc.")
    .padding()
    .background(.green)
Monsters, Inc.
(green background extends around the padded area)
// Background THEN padding
Text("Monsters, Inc.")
    .background(.green)
    .padding()
Monsters, Inc.
(green background hugs the text, padding is outside it)

In the first example, padding is added first, making the view larger, and then the green background covers the entire padded area. In the second example, the background is applied to the smaller text view first, and then transparent padding is added outside.

Common Modifiers

Here are modifiers you will use constantly:

Text("Up")
    .font(.title)           // Changes text size
    .foregroundStyle(.purple) // Changes text color
    .padding()               // Adds space around the view
    .background(.yellow)     // Adds a background color
    .clipShape(RoundedRectangle(cornerRadius: 10)) // Rounds the corners
Up
(purple text on a yellow rounded rectangle)

Each modifier adds one visual change. You can read the chain top to bottom to understand the final appearance.

Common Mistakes

Forgetting .resizable() on Custom Images

Without .resizable(), a custom image displays at its full pixel size, which can fill the entire screen or overflow it.

// ❌ Don't do this
Image("carl-poster")
    .frame(width: 100, height: 100)
// ✅ Do this instead
Image("carl-poster")
    .resizable()
    .scaledToFit()
    .frame(width: 100, height: 100)

The .frame() modifier sets the available space, but only .resizable() tells the image to actually scale itself to fit that space.

Putting Modifiers in the Wrong Order

Since modifiers create new views from the outside in, swapping the order produces different results. If your background looks wrong or your padding seems off, check the modifier order.

// ❌ Background only covers the text, not the padding
Text("Inside Out")
    .background(.cyan)
    .padding()
// ✅ Background covers the full padded area
Text("Inside Out")
    .padding()
    .background(.cyan)

Using a VStack When You Need an HStack

Beginners sometimes default to VStack for everything. If elements should sit side by side (like a star icon next to a rating number), use HStack.

// ❌ Star and text stacked vertically
VStack {
    Image(systemName: "star.fill")
    Text("4.9")
}
// ✅ Star and text side by side
HStack {
    Image(systemName: "star.fill")
    Text("4.9")
}

What’s Next?

  • A view is a struct conforming to the View protocol with a body property.
  • Text displays strings; Image displays icons and pictures.
  • VStack, HStack, and ZStack arrange views vertically, horizontally, and in layers.
  • Modifiers chain together to customize views — order matters.
  • Nest stacks inside each other to build complex layouts.

Now that you can create and combine views, it is time to learn how SwiftUI decides where to place them and how much space they get. Continue to The SwiftUI Layout System to master frames, padding, and spacers.