TechnologiesSwiftUIToolbars and Commands

ContentMarginPlacement struct

iOSmacOStvOSwatchOSvisionOSiOS 17.0+✓ renders

The placement of margins.

How it works

ContentMarginPlacement identifies where a content margin lands within a view, letting you distinguish the margin applied to the scrollable content from the margin applied to the scroll view's indicators or other ancillary elements. You pass it to the contentMargins(_:_:for:) modifier so that an inset can target one region without disturbing the others. Reach for it when a scroll view needs breathing room around its rows while keeping the scroll indicators flush to the edge, or vice versa.

  1. Pass a placement to contentMargins(_:_:for:)

    The for: parameter of the content-margins modifier takes a ContentMarginPlacement and decides which region the inset affects. In the example, .contentMargins(.horizontal, 24, for: .scrollContent) routes a 24-point horizontal inset specifically to the placement named by .scrollContent.

  2. Use .scrollContent to inset the scrollable area

    The .scrollContent placement targets the layout of the content itself, so the inset moves the rows inward while leaving the scroll indicators where they are. Here .scrollContent is what gives every Text("Row \(i)") its left and right breathing room inside the ScrollView.

  3. Choose an edge set alongside the placement

    ContentMarginPlacement works in tandem with the Edge.Set you supply as the first argument, which scopes the inset to particular sides. The example pairs the .scrollContent placement with .horizontal, so the 24-point margin applies only to the leading and trailing edges and not the top or bottom.

  4. Pick a default placement when you omit for:

    ContentMarginPlacement also offers .automatic, the value used when you call contentMargins without a for: argument, which lets SwiftUI apply the inset to the standard region for the context. Naming .scrollContent explicitly, as the example does, overrides that default to target the content layout precisely.

Try it — Change for: .scrollContent to for: .automatic (or drop the for: argument) and watch how the horizontal inset's relationship to the scroll indicators shifts.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

ContentMarginPlacement.swift
struct ContentMarginPlacementDemo: View {
    var body: some View {
        ScrollView {
            VStack(spacing: 12) {
                ForEach(1..<8) { i in
                    Text("Row \(i)")
                        .frame(maxWidth: .infinity)
                        .padding()
                        .background(.blue.opacity(0.15))
                        .cornerRadius(8)
                }
            }
        }
        .contentMargins(.horizontal, 24, for: .scrollContent)
        .padding()
    }
}
Live preview
Row 1 Row 2 Row 3 Row 4 Row 5 Row 6 Row 7
Row 1 Row 2 Row 3 Row 4 Row 5 Row 6 Row 7
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →