TechnologiesSwiftUIScrolling

PagingScrollTargetBehavior struct

iOSmacOStvOSwatchOSvisionOSiOS 17.0+✓ renders

The scroll behavior that aligns scroll targets to container-based geometry.

How it works

PagingScrollTargetBehavior is a scroll target behavior that snaps a scroll view's resting position to page boundaries, so each gesture settles on a whole page rather than coming to rest at an arbitrary offset. Reach for it when you want a paged, carousel-like feel — full-screen onboarding pages, image galleries, or horizontally swiped cards — where the content advances one container-sized page at a time. It replaces the manual offset math and gesture tracking you would otherwise need to recreate UIScrollView-style paging, expressing the intent declaratively through the scroll view's modifier chain.

  1. Apply the behavior with scrollTargetBehavior(.paging)

    The behavior is attached to the scroll view itself through the scrollTargetBehavior(_:) modifier, which takes a ScrollTargetBehavior value. The .paging shorthand resolves to a PagingScrollTargetBehavior instance, so writing .scrollTargetBehavior(.paging) is all it takes to switch the container from free scrolling to page-aligned snapping.

  2. Mark the snap targets with scrollTargetLayout()

    Paging needs to know which subviews are candidate landing points. Calling scrollTargetLayout() on the scrollable stack — here the HStack of cards — promotes its direct children into scroll targets, and PagingScrollTargetBehavior aligns the rest position to the page that encloses those targets. Without this layout, the behavior has no targets to page between.

  3. Page within a scroll axis

    PagingScrollTargetBehavior derives a page from the scroll view's container size along its scrolling axis. Because the ScrollView(.horizontal) here scrolls sideways, each page spans the visible width, and a swipe advances by exactly one screenful — the width: 220 of an individual RoundedRectangle does not define the page; the container does.

  4. Construct it directly when you need the type

    Although .paging is the idiomatic spelling, PagingScrollTargetBehavior is a public struct you can name explicitly — .scrollTargetBehavior(PagingScrollTargetBehavior()) is equivalent. Spelling out the type is useful when assigning the behavior to a variable or returning it from a helper that vends a configured behavior.

Try it — Change .scrollTargetBehavior(.paging) to .scrollTargetBehavior(.viewAligned) and watch the scroll view settle on whichever card is nearest rather than snapping a full page at a time.

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.

PagingScrollTargetBehavior.swift
struct PagingScrollTargetBehaviorDemo: View {
    let colors: [Color] = [.red, .green, .blue, .orange]

    var body: some View {
        ScrollView(.horizontal) {
            HStack(spacing: 16) {
                ForEach(0..<colors.count, id: \.self) { i in
                    RoundedRectangle(cornerRadius: 16)
                        .fill(colors[i])
                        .frame(width: 220, height: 280)
                        .overlay(Text("Page \(i + 1)").font(.title).bold().foregroundStyle(.white))
                }
            }
            .scrollTargetLayout()
        }
        .scrollTargetBehavior(.paging)
        .padding()
    }
}
Live preview
Page \(i + 1) Page \(i + 1) Page \(i + 1) Page \(i + 1)
Page \(i + 1) Page \(i + 1) Page \(i + 1) Page \(i + 1)
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →