TechnologiesSwiftUI

ViewAlignedScrollTargetBehavior struct

iOSmacOStvOSwatchOSvisionOSiOS 17.0+✓ renders

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

How it works

ViewAlignedScrollTargetBehavior is a scroll target behavior that snaps a scroll view to rest on the boundaries of the views in its content, so scrolling always settles with a view aligned to the scroll view's edge rather than stopping at an arbitrary offset. Reach for it when you're building a paged or carousel-style scroll view of discrete items and you want the gesture to land on whole views instead of free-scrolling. You don't construct it directly; you apply it through the .viewAligned static accessor on ScrollTargetBehavior and pair it with a layout that marks which views are the snap targets.

  1. Apply the behavior with scrollTargetBehavior(.viewAligned)

    The scrollTargetBehavior(_:) modifier installs a ScrollTargetBehavior on a scroll view, and passing .viewAligned selects ViewAlignedScrollTargetBehavior. This is what tells the scroll view to align its resting position to your content's views. In the example it's attached to the ScrollView as .scrollTargetBehavior(.viewAligned).

  2. Declare the snap targets with scrollTargetLayout()

    ViewAlignedScrollTargetBehavior needs to know which views are candidates to align to. Applying scrollTargetLayout() to a container marks each of that container's subviews as a scroll target, so the behavior snaps to their leading edges. Here the .scrollTargetLayout() modifier is placed on the HStack, making each card produced by the ForEach an alignment target.

  3. Pair the behavior with the scroll axis

    The behavior aligns along the scroll view's scrolling axis, so it works with whichever axis you configure. Because the ScrollView is created as ScrollView(.horizontal), .viewAligned snaps horizontally, settling on one card at a time as the reader swipes left and right.

  4. Provide distinct views to align to

    Each subview inside the scrollTargetLayout container becomes its own snap point, so the content should be a sequence of discrete views. In the example the ForEach over colors emits one RoundedRectangle per item, each given a fixed .frame(width: 220, height: 160), which gives ViewAlignedScrollTargetBehavior evenly sized, clearly bounded targets to rest on.

Try it — Remove the .scrollTargetLayout() modifier from the HStack and scroll: without marked targets the behavior has nothing to align to and the scroll view drifts to arbitrary offsets again, showing exactly what ViewAlignedScrollTargetBehavior contributes.

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.

ViewAlignedScrollTargetBehavior.swift
struct ViewAlignedScrollTargetBehaviorDemo: View {
    let colors: [(String, Color)] = [("Red", .red), ("Green", .green), ("Blue", .blue), ("Orange", .orange)]

    var body: some View {
        ScrollView(.horizontal) {
            HStack(spacing: 16) {
                ForEach(colors, id: \.0) { item in
                    RoundedRectangle(cornerRadius: 16)
                        .fill(item.1)
                        .frame(width: 220, height: 160)
                        .overlay(Text(item.0).font(.title).bold().foregroundStyle(.white))
                }
            }
            .scrollTargetLayout()
        }
        .scrollTargetBehavior(.viewAligned)
        .padding()
    }
}
Live preview
Red Green Blue Orange
Red Green Blue Orange
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →