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 behindclipShape + 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 + textscaleEffect + 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 sizerotationEffect + 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 movementWhen 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.