Skip to content
axiom-swiftui-containers-ref logo

SwiftUI Containers Reference

axiom-swiftui-containers-ref

Reference — SwiftUI stacks, grids, outlines, and scroll enhancements through iOS 26

SKILL.md

Full skill instructions

SwiftUI Containers Reference

Stacks, grids, outlines, and scroll enhancements. iOS 14 through iOS 26.

Sources: WWDC 2020-10031, 2022-10056, 2023-10148, 2024-10144, 2025-256

Quick Decision

Use CaseContaineriOS
Fixed views vertical/​horizontalVStack / HStack13+
Overlapping viewsZStack13+
Large scrollable listLazyVStack / LazyHStack14+
Multi-column gridLazyVGrid14+
Multi-row grid (horizontal)LazyHGrid14+
Static grid, precise alignmentGrid16+
Hierarchical data (tree)List with children:14+
Custom hierarchiesOutlineGroup14+
Show/​hide contentDisclosureGroup14+

Part 1: Stacks

VStack, HStack, ZStack

VStack(alignment: .leading, spacing: 12) {
    Text("Title")
    Text("Subtitle")
}

HStack(alignment: .top, spacing: 8) {
    Image(systemName: "star")
    Text("Rating")
}

ZStack(alignment: .bottomTrailing) {
    Image("photo")
    Badge()
}

ZStack alignments: .center (default), .top, .bottom, .leading, .trailing, .topLeading, .topTrailing, .bottomLeading, .bottomTrailing

Spacer

HStack {
    Text("Left")
    Spacer()
    Text("Right")
}

Spacer(minLength: 20)  // Minimum size

LazyVStack, LazyHStack (iOS 14+)

Render children only when visible. Use inside ScrollView.

ScrollView {
    LazyVStack(spacing: 0) {
        ForEach(items) { item in
            ItemRow(item: item)
        }
    }
}

Pinned Section Headers

ScrollView {
    LazyVStack(pinnedViews: [.sectionHeaders]) {
        ForEach(sections) { section in
            Section(header: SectionHeader(section)) {
                ForEach(section.items) { item in
                    ItemRow(item: item)
                }
            }
        }
    }
}

Part 2: Grids

Grid (iOS 16+)

Non-lazy grid with precise alignment. Loads all views at once.

Grid(alignment: .leading, horizontalSpacing: 10, verticalSpacing: 10) {
    GridRow {
        Text("Name")
        TextField("Enter name", text: $name)
    }
    GridRow {
        Text("Email")
        TextField("Enter email", text: $email)
    }
}

Modifiers:

  • gridCellColumns(_:) — Span multiple columns
  • gridColumnAlignment(_:) — Override column alignment
Grid {
    GridRow {
        Text("Header").gridCellColumns(2)
    }
    GridRow {
        Text("Left")
        Text("Right").gridColumnAlignment(.trailing)
    }
}

LazyVGrid (iOS 14+)

Vertical-scrolling grid. Define columns; rows grow unbounded.

let columns = [
    GridItem(.flexible()),
    GridItem(.flexible()),
    GridItem(.flexible())
]

ScrollView {
    LazyVGrid(columns: columns, spacing: 16) {
        ForEach(items) { item in
            ItemCard(item: item)
        }
    }
}

LazyHGrid (iOS 14+)

Horizontal-scrolling grid. Define rows; columns grow unbounded.

let rows = [GridItem(.fixed(100)), GridItem(.fixed(100))]

ScrollView(.horizontal) {
    LazyHGrid(rows: rows, spacing: 16) {
        ForEach(items) { item in
            ItemCard(item: item)
        }
    }
}

GridItem.Size

SizeBehavior
.fixed(CGFloat)Exact width/​height
.flexible(minimum:maximum:)Fills space equally
.adaptive(minimum:maximum:)Creates as many as fit
// Adaptive: responsive column count
let columns = [GridItem(.adaptive(minimum: 150))]

Part 3: Outlines

List with Hierarchical Data (iOS 14+)

struct FileItem: Identifiable {
    let id = UUID()
    var name: String
    var children: [FileItem]?  // nil = leaf
}

List(files, children: \.children) { file in
    Label(file.name, systemImage: file.children != nil ? "folder" : "doc")
}
.listStyle(.sidebar)

OutlineGroup (iOS 14+)

For custom hierarchical layouts outside List.

List {
    ForEach(canvases) { canvas in
        Section(header: Text(canvas.name)) {
            OutlineGroup(canvas.graphics, children: \.children) { graphic in
                GraphicRow(graphic: graphic)
            }
        }
    }
}

DisclosureGroup (iOS 14+)

@State private var isExpanded = false

DisclosureGroup("Advanced Options", isExpanded: $isExpanded) {
    Toggle("Enable Feature", isOn: $feature)
    Slider(value: $intensity)
}

Part 4: Common Patterns

Photo Grid

let columns = [GridItem(.adaptive(minimum: 100), spacing: 2)]

ScrollView {
    LazyVGrid(columns: columns, spacing: 2) {
        ForEach(photos) { photo in
            AsyncImage(url: photo.thumbnailURL) { image in
                image.resizable().aspectRatio(1, contentMode: .fill)
            } placeholder: { Color.gray }
            .aspectRatio(1, contentMode: .fill)
            .clipped()
        }
    }
}

Horizontal Carousel

ScrollView(.horizontal, showsIndicators: false) {
    LazyHStack(spacing: 16) {
        ForEach(items) { item in
            CarouselCard(item: item).frame(width: 280)
        }
    }
    .padding(.horizontal)
}

File Browser

List(selection: $selection) {
    OutlineGroup(rootItems, children: \.children) { item in
        Label {
            Text(item.name)
        } icon: {
            Image(systemName: item.children != nil ? "folder.fill" : "doc.fill")
        }
    }
}
.listStyle(.sidebar)

Part 5: Performance

When to Use Lazy

SizeScrollable?Use
1-20NoVStack/​HStack
1-20YesVStack/​HStack in ScrollView
20-100YesLazyVStack/​LazyHStack
100+YesLazyVStack/​LazyHStack or List
Grid <50NoGrid
Grid 50+YesLazyVGrid/​LazyHGrid

Cache GridItem arrays — define outside body:

struct ContentView: View {
    let columns = [GridItem(.adaptive(minimum: 150))]  // ✅
    var body: some View {
        LazyVGrid(columns: columns) { ... }
    }
}

iOS 26 Performance

  • 6x faster list loading for 100k+ items
  • 16x faster list updates
  • Reduced dropped frames in scrolling
  • Nested ScrollViews with lazy stacks now properly defer loading:
ScrollView(.horizontal) {
    LazyHStack {
        ForEach(photoSets) { set in
            ScrollView(.vertical) {
                LazyVStack {
                    ForEach(set.photos) { PhotoView(photo: $0) }
                }
            }
        }
    }
}

Part 6: Scroll Enhancements

containerRelativeFrame (iOS 17+)

Size views relative to scroll container.

ScrollView(.horizontal) {
    LazyHStack {
        ForEach(cards) { card in
            CardView(card: card)
                .containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 16)
        }
    }
}

scrollTargetLayout (iOS 17+)

Enable snapping.

ScrollView(.horizontal) {
    LazyHStack {
        ForEach(items) { ItemCard(item: $0) }
    }
    .scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)

scrollPosition (iOS 17+)

Track topmost visible item. Requires .id() on each item.

@State private var position: Item.ID?

ScrollView {
    LazyVStack {
        ForEach(items) { item in
            ItemRow(item: item).id(item.id)
        }
    }
}
.scrollPosition(id: $position)

scrollTransition (iOS 17+)

.scrollTransition { content, phase in
    content
        .opacity(1 - abs(phase.value) * 0.5)
        .scaleEffect(phase.isIdentity ? 1.0 : 0.75)
}

onScrollGeometryChange (iOS 18+)

.onScrollGeometryChange(for: Bool.self) { geo in
    geo.contentOffset.y < geo.contentInsets.top
} action: { _, isTop in
    showBackButton = !isTop
}

onScrollVisibilityChange (iOS 18+)

VideoPlayer(player: player)
    .onScrollVisibilityChange(threshold: 0.2) { visible in
        visible ? player.play() : player.pause()
    }

Resources

WWDC: 2020-10031, 2022-10056, 2023-10148, 2024-10144, 2025-256

Docs: /​swiftui/​lazyvstack, /​swiftui/​lazyvgrid, /​swiftui/​lazyhgrid, /​swiftui/​grid, /​swiftui/​outlinegroup, /​swiftui/​disclosuregroup

Skills: axiom-swiftui-layout, axiom-swiftui-layout-ref, axiom-swiftui-nav, axiom-swiftui-26-ref

More Other skills

Delegate independent tasks to specialized agents working concurrently with isolated context.

295.4K 206.3K
View

Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.

179.7K 100.1K
View

Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.

179.7K 89.5K
View

A set of resources to help me write all kinds of internal communications, using the formats that my company likes to use. Claude should use this skill whenever asked to write some sort of internal communications (status reports, leadership updates, 3P updates, company newsletters, FAQs, incident reports, project updates, etc.).

179.7K 76.1K
View

Fundamental design principles for writing maintainable, testable Python code.

40.2K 21.9K
View

Modern responsive layouts using container queries, fluid typography, CSS Grid, and mobile-first strategies.

40.2K 20K
View

Generate Playwright tests from scenarios using interactive browser exploration and validation.

39.7K 18.2K
View

Modern React state management with Redux Toolkit, Zustand, Jotai, and React Query for every state category.

40.2K 14.7K
View

GDPR-compliant data handling with consent management, data subject rights, and privacy controls.

40.2K 14.3K
View

Python error handling patterns including input validation, exception hierarchies, and partial failure handling. Use when implementing validation logic, designing exception strategies, handling batch processing failures, or building robust APIs.

40.2K 13.5K
View

Detailed multi-file refactor planning with safety checks and rollback guidance.

39.7K 13K
View