Adding Padding in SwiftUI View | SwiftUI Bootcamp #11
Padding is how you create breathing room in your UI — between text and a button background, between a card and the screen edges, between a title and its description. After this lesson you'll understand how padding interacts with background layers and how to build a polished card component from scratch.
What You'll Learn
- The four forms of
.padding(): none (all sides), specific edges, specific edges with a value, and all sides with a value - Why applying padding before a background produces a different visual than applying it after
- How to build a card component with rounded corners and a drop shadow using only padding and background
Mental Model
Think of padding like a protective foam insert in a shipping box. The foam goes around the content, and the box then wraps around the foam. In SwiftUI, if you apply .padding() before .background(), the background covers the content plus the foam — the colored background fills the padded region. If you apply .background() before .padding(), the background wraps the content alone, and the padding adds space outside the background — leaving an uncolored gap between the background and the next view.
This before/after order is the most important thing to understand about padding.
Detailed Explanation
.padding() with no arguments applies the system-default padding (16pt on all sides on most devices). This value scales appropriately with device size and Dynamic Type settings, which is why it's preferred over a hard-coded .padding(16) for most use cases.
.padding(.bottom, 20) applies 20pt of padding to the bottom only. The first argument is one of SwiftUI's Edge.Set values: .top, .bottom, .leading, .trailing, .horizontal (left+right), .vertical (top+bottom). Multiple edges can be combined: .padding([.leading, .trailing], 20).
.padding(.horizontal, 10) is shorthand for .padding([.leading, .trailing], 10). This is the most common modifier for giving content breathing room from screen edges.
Padding and background order: .padding().background(Color.white) makes a white background that includes the padded region. .background(Color.white).padding() makes a white background that doesn't include the padded region — there's a transparent gap around the white area. The sample uses the first approach (padding before background) to produce a full-width white card.
Code Structure
The sample is in PaddingAndSpacerBootcamp.swift and builds a card with a title, a body description, padding on multiple levels, a white rounded background, and a drop shadow. Padding is applied in layers — first to individual elements, then to the whole VStack, then to the outer edges of the card.
Complete Code
PaddingAndSpacerBootcamp.swift
import SwiftUI
struct PaddingAndSpacerBootcamp: View {
var body: some View {
VStack(alignment: .leading) {
Text("Hello, World!")
.font(.largeTitle)
.fontWeight(.semibold)
.padding(.bottom, 20) // adds 20pt gap between the title and the description below it
Text("This is the description of what we will do on this screen. It is multiple lines and we will align the text to the leading edge.")
}
.padding() // adds system-default padding (16pt) on all four sides inside the card
.padding(.vertical, 10) // adds an additional 10pt on top and bottom for extra breathing room
.background(
Color.white
.cornerRadius(10) // rounds the white card's corners to 10pt radius
.shadow(
color: Color.black.opacity(0.3), // semi-transparent black shadow for depth
radius: 10, // softness of the shadow edge
x: 0.0, y: 10) // shadow drops downward (positive y)
)
.padding(.horizontal, 10) // adds 10pt on left and right so the card doesn't touch screen edges
}
}
struct PaddingAndSpacerBootcamp_Previews: PreviewProvider {
static var previews: some View {
PaddingAndSpacerBootcamp()
}
}Code Walkthrough
VStack(alignment: .leading)— The stack aligns both text views to the leading edge. Without this, both would center-align, which looks wrong for body text..padding(.bottom, 20)on the title — Adds space between the large title and the description below it. This is the "inner" spacing for content hierarchy — titles need more separation from body text than body text needs from other elements..padding()— Applied to the entireVStack, this adds 16pt padding on all sides between the text content and the card's visual edge. This is what prevents the text from running to the edge of the white card..padding(.vertical, 10)— Adds another 10pt on top and bottom on top of the system padding. The result is 26pt top and bottom padding and 16pt left and right..background(Color.white.cornerRadius(10).shadow(...))— The.background()comes after all the padding, so the white rounded rectangle covers the entire padded area. Crucially,.cornerRadius()and.shadow()are applied to theColor.whiteshape, not to theVStack..cornerRadius(10)on the Color — This applies rounding to the background shape. Note: in newer SwiftUI APIs,.background(Color.white, in: RoundedRectangle(cornerRadius: 10))is the preferred syntax, but the chained approach shown here is compatible with older iOS versions..padding(.horizontal, 10)— The outermost padding prevents the card from touching the screen edges. This is distinct from the inner padding — it creates the visible margin between the card and the device bezel.
Common Mistakes
Mistake: Applying .background() before .padding() and wondering why the background doesn't cover the padded area Order matters. .background() before .padding() places the colored background on the unpadded content, then adds empty space outside. .padding() before .background() makes the background fill the padded region. For card-style components, always pad first, then background.
Mistake: Hard-coding .padding(16) instead of .padding() The system-default padding from .padding() is designed to be appropriate for each device size and is consistent with Apple's layout guidelines. Hard-coding .padding(16) breaks this adaptive behavior. Only specify a custom value when you have a specific design reason to deviate from the system default.
Mistake: Stacking padding modifiers and losing track of the cumulative total In the sample, the VStack has .padding() (16pt) and .padding(.vertical, 10) — resulting in 26pt of vertical padding and 16pt of horizontal padding. This is intentional but easy to lose track of. When debugging unexpected whitespace, add a colored .background() after each padding modifier to visualize each layer.
Key Takeaways
- Apply
.padding()before.background()to include the padded area inside the background color - Use
.padding()(no arguments) for adaptive system-default spacing; specify values only when deviating from the system default - The outermost
.padding(.horizontal)creates the card margin — keep it separate from the inner content padding
Last updated: June 27, 2026