SwiftUI.cc
Snippets
StylingCustom StylingIntermediate

Reusable SwiftUI ViewModifier and Shape Styling

Move repeated visual decisions into ViewModifier and Shape extensions so the UI reads like product language.

5 min readUpdated 2026-06
Surface card modifier
import SwiftUI

struct SurfaceCardModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding(16)
            .background(.background, in: RoundedRectangle(cornerRadius: 16))
            .overlay {
                RoundedRectangle(cornerRadius: 16)
                    .strokeBorder(.quaternary)
            }
    }
}

extension View {
    func surfaceCard() -> some View { modifier(SurfaceCardModifier()) }
}
Use this when

A group of modifiers appears in several unrelated views.

The style has a semantic product name, such as surface card or warning panel.

Shape-specific styling should remain available to any Shape.

Avoid this when

The abstraction saves only one line and makes the call site less clear.

The modifier needs too many parameters and becomes a hidden component.

The repeated code belongs in a full reusable View instead.

Implementation notes

A good modifier name explains the product role, not just the visual ingredients.
Shape extensions are useful when fill, trim, stroke, or strokeBorder patterns repeat.
Prefer small modifiers that compose well over one giant theme modifier.

Checklist

Check light mode, dark mode, and high contrast.

Keep layout-changing modifiers intentional.

Document style names in your design system when the team grows.

Related reference