Skip to main content
.scrollTargetLayout(isEnabled?: boolean): Component;

Parameters

isEnabled
boolean
default:true
Whether scroll target layout is enabled. When true, marks the container’s children as scroll targets.

Support

Usage

Horizontal scroll snapping

ScrollView({ axis: "horizontal" }, [
    HStack({ spacing: 16 }, [
        ForEach(items, (item) => CardView({ item }))
    ]).scrollTargetLayout()
]).scrollTargetBehavior("viewAligned")

Vertical scroll snapping

ScrollView({ axis: "vertical" }, [
    VStack({ spacing: 20 }, [
        ForEach(sections, (section) => SectionView({ section }))
    ]).scrollTargetLayout()
]).scrollTargetBehavior("viewAligned")

Conditional scroll targets

ScrollView({ axis: "horizontal" }, [
    HStack({ spacing: 12 }, [
        ForEach(cards, (card) => CardItem({ card }))
    ]).scrollTargetLayout(shouldEnableSnapping)
]).scrollTargetBehavior("viewAligned")

Examples

function ImageCarousel(props) {
    const images = ["image1.jpg", "image2.jpg", "image3.jpg"];

    return ScrollView({ axis: "horizontal", showsIndicators: false }, [
        HStack({ spacing: 0 }, [
            ForEach(images, (imageUrl) =>
                Image({ url: imageUrl })
                    .frame({ width: 300, height: 400 })
                    .cornerRadius(12)
            )
        ]).scrollTargetLayout()
    ])
    .scrollTargetBehavior("paging");
}

Card stack with view-aligned snapping

function CardStack(props) {
    return ScrollView({ axis: "horizontal" }, [
        HStack({ spacing: 16 }, [
            ForEach(props.items, (item) =>
                VStack({ alignment: "leading" }, [
                    Text(item.title).font("headline"),
                    Text(item.description).font("body"),
                    Spacer(),
                    Button("View Details", () => {})
                ])
                .padding(20)
                .frame({ width: 280, height: 350 })
                .background(Color("background"))
                .cornerRadius(16)
                .shadow({ radius: 4 })
            )
        ])
        .padding({ horizontal: 20 })
        .scrollTargetLayout()
    ])
    .scrollTargetBehavior("viewAligned");
}

Full-screen sections

function OnboardingFlow(props) {
    const screens = [
        { title: "Welcome", description: "Get started with our app" },
        { title: "Features", description: "Discover what you can do" },
        { title: "Ready", description: "Let's begin!" }
    ];

    return ScrollView({ axis: "horizontal", showsIndicators: false }, [
        HStack({ spacing: 0 }, [
            ForEach(screens, (screen) =>
                VStack({ spacing: 20 }, [
                    Text(screen.title).font("largeTitle").bold(),
                    Text(screen.description).font("body")
                ])
                .frame({ width: GeometryProxy.size.width })
                .padding(40)
            )
        ]).scrollTargetLayout()
    ])
    .scrollTargetBehavior("paging");
}

Notes

  • Use scrollTargetLayout() on a layout container (HStack, VStack, LazyHStack, LazyVStack) inside a ScrollView
  • Must be combined with scrollTargetBehavior() on the parent ScrollView to enable snapping
  • When enabled, each direct child of the container becomes a scroll target
  • Works with both horizontal and vertical scroll views
  • Particularly useful for carousels, onboarding flows, and card galleries