View modifiers in SwiftUI are methods that you call on a View or another view modifier to create a new, modified version of the original view. You can use built-in view modifiers or create your own by conforming to the ViewModifier protocol.
Text("Hello")
.font(.largeTitle)
.foregroundColor(.blue)
.padding()
.background(.gray)
Each modifier creates a new view by applying a change to the one before it, think of it like a series of filters applied to a photo.
Order doesn’t matter when a modifier only sets or overrides a property, and doesn’t wrap or transform the view hierarchy:
- .font(_:)
- .foregroundColor(_:)
- .bold(), .italic(), .underline()
- .lineLimit(_:)
- .multilineTextAlignment(_:)
- .environment(...)
- .allowsHitTesting(_:)
Modifier order matters when it changes how your view looks, lays out, or reacts:
padding
+ background
// Yellow covers text + padding.
Text("Hello")
.padding()
.background(Color.yellow)
+------------------------+ ← yellow background
| "Hello" padded |
+------------------------+
// Yellow covers only text, then the whole block is padded.
Text("Hello")
.background(Color.yellow)
.padding()
+----------------------------+ ← outer padding
| "Hello" on yellow box |
+----------------------------+
frame
+ background
// Blue background fills the entire 200×100 frame.
Text("Hi")
.frame(width: 200, height: 100)
.background(Color.blue)
+--------------------------+ ← blue background (200×100)
| "Hi" |
+--------------------------+
// Blue only behind text, then centered inside the 200×100 frame.
Text("Hi")
.background(Color.blue)
.frame(width: 200, height: 100)
+--------------------------+ ← frame (200×100, mostly empty)
| +---------+ |
| | "Hi"🔵 | | ← small blue box just behind text
| +---------+ |
+--------------------------+
opacity
// Both text and background are semi-transparent.
Text("Hello")
.background(Color.red)
.opacity(0.5)
[ "Hello" + red box ] → faded together (50% opacity)
// Only text is semi-transparent, background stays solid.
Text("Hello")
.opacity(0.5)
.background(Color.red)
[ "Hello" faded 50% ] + solid red box behind
clipShape
+ shadow
// Shadow gets clipped off (looks like no shadow).
Circle()
.fill(Color.blue)
.shadow(radius: 10)
.clipShape(Circle())
(blue circle only, shadow cut off by clipping)
// Shadow remains visible outside the circle.
Circle()
.fill(Color.blue)
.clipShape(Circle())
.shadow(radius: 10)
(blue circle + shadow glowing outside it)
overlay
+ background
// Yellow behind text, red stroke drawn on top.
Text("SwiftUI")
.background(Color.yellow)
.overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.red))
[ yellow box ] + "SwiftUI"
+ red border drawn on top
// Red stroke tightly fits text bounds, yellow behind both.
Text("SwiftUI")
.overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.red))
.background(Color.yellow)
"SwiftUI"
+ red border tightly around text
+ yellow fills behind border + text
scaleEffect
+ padding
// Text scales first, then padding is added around the scaled result.
Text("Boom")
.scaleEffect(2)
.padding()
+------------------------+
| [ "Boom" ×2 size ] | ← then padded
+------------------------+
// Padding is added first, then the entire block is scaled up (including padding).
Text("Boom")
.padding()
.scaleEffect(2)
+---------------------------+
| "Boom" with padding | ← padding box also scaled
+---------------------------+
↑ whole box ×2 size
rotationEffect
+ offset
// Text is rotated in place, then shifted right by 50.
Text("Spin")
.rotationEffect(.degrees(45))
.offset(x: 50, y: 0)
"Spin" rotated ↗ 45°
then shifted right →
// Text is shifted right, then the offset path is rotated (moves diagonally).
Text("Spin")
.offset(x: 50, y: 0)
.rotationEffect(.degrees(45))
"Spin" moved right first →
then whole offset path rotates ↗
result: diagonal movement
When working with SwiftUI, it helps to think of modifiers as layers: geometry comes first, then styling, then interactivity. By experimenting with different orders — and remembering that the last modifier you write is the outermost wrapper — you’ll gain predictable control over your views while keeping performance in check.