TechnologiesSwiftUI

LazyHGrid struct

iOSmacOStvOSwatchOSvisionOSiOS 14.0+✓ renders

A container view that arranges its child views in a grid that

How it works

A LazyHGrid arranges its child views in a grid that grows horizontally, adding a new column as needed to hold each successive item. Like its sibling LazyVGrid, it is lazy: it creates and lays out only the views currently within or near the visible region, so it can present large or open-ended collections without paying the cost of building every cell up front. Reach for a LazyHGrid when content scrolls sideways and you want to pin a fixed number of rows while columns extend off-screen.

  1. Define the rows with an array of GridItem

    The number of GridItem values you pass fixes how many rows the grid has; each item describes how its row is sized and spaced. Here rows holds two GridItem(.fixed(40)) values, so every column is two cells tall with each row locked to 40 points.

  2. Create the grid with init(rows:spacing:content:)

    The primary initializer takes the row template, an optional spacing between columns, and a content closure that produces the cells. In the example LazyHGrid(rows: rows, spacing: 12) lays out its children across two rows with 12 points between adjacent columns.

  3. Supply cells through the content closure

    The trailing closure is a view builder, so you can emit views directly or generate them dynamically. Here a ForEach(1...12, id: \.self) feeds twelve Text views into the grid, which flows them down the first column, then the next, filling rows before advancing horizontally.

  4. Wrap it in a horizontal ScrollView to reveal the laziness

    LazyHGrid sizes itself to its content and relies on a scrolling container to expose columns beyond the viewport; only then does its on-demand cell creation pay off. The example places it inside ScrollView(.horizontal) so the columns of numbers scroll left and right.

  5. Control sizing per row with the GridItem cases

    Each GridItem can be .fixed, .flexible, or .adaptive, and also carries its own spacing and alignment, letting individual rows differ in height. Swapping the .fixed(40) entries for .flexible() lets the rows divide the available vertical space instead of pinning to an exact 40 points.

Try it — Add a third GridItem(.fixed(40)) to the rows array and watch the grid lay its twelve numbers out across three rows, packing the columns more tightly.

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.

LazyHGrid.swift
struct LazyHGridDemo: View {
    let rows = [GridItem(.fixed(40)), GridItem(.fixed(40))]
    var body: some View {
        ScrollView(.horizontal) {
            LazyHGrid(rows: rows, spacing: 12) {
                ForEach(1...12, id: \.self) { i in
                    Text("\(i)")
                        .frame(width: 40, height: 40)
                        .background(Color.blue.opacity(0.2))
                        .cornerRadius(8)
                }
            }
        }
        .padding()
    }
}
Live preview
1 2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10 11
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →