Skip to content

Grid Row

Utilities for controlling how grid items span and where they start and end across grid rows. The numeric forms are generative and unbounded — any positive integer works (row-span-2, row-span-13, row-start-99, etc.).

The Wrap-based grid renderer derives per-tile height from row-* utilities only when the parent uses column-flow mode (grid-flow-col grid-rows-N). In row-flow mode (the default, grid grid-cols-N), per-tile height is determined by the cell’s natural height; row-span only sizes children inside a column-flow grid.

Use row-span-<number> to make an element span the specified number of rows. row-span-full spans all rows of the parent grid.

Style('grid grid-flow-col grid-rows-3 gap-4', children: [
Style('row-span-3 ...', child: Text('01')),
Style('col-span-2 ...', child: Text('02')),
Style('col-span-2 row-span-2 ...', child: Text('03')),
])

Use row-start-<number> and row-end-<number> to position a grid item at a specific row line. When both are set without an explicit row-span, the item’s effective height is derived as end − start (CSS exclusive-end semantics, so row-start-1 row-end-3 is two rows tall).

Because the renderer is Wrap-based and lays children out sequentially, row-start / row-end only contribute to the item’s height; they do not move the item to a specific cell. To demonstrate row placement visually, fill the empty cells with explicit placeholder tiles. Tailwind’s docs do the same with their <Stripes> placeholders.

Style('grid grid-flow-col grid-rows-3 gap-4', children: [
Style('row-span-2 row-start-2 ...', child: Text('01')),
Style('row-span-2 row-end-3 ...', child: Text('02')),
Style('row-start-1 row-end-4 ...', child: Text('03')),
])

The bracket form accepts any positive integer for each placement utility:

Style('row-span-[7]', child: ...) // rowSpan = 7
Style('row-start-[2]', child: ...) // rowStart = 2
Style('row-end-[5]', child: ...) // rowEnd = 5
Style('row-[3]', child: ...) // bare shorthand → rowStart = 3
ClassDescription
row-autoClear explicit placement; the item takes the next available cell.
row-<number>Bare shorthand — equivalent to row-start-<number> (CSS grid-row: <N> resolves to start <N> with auto end).
row-[<value>]Arbitrary integer alias for row-start-[<value>].
row-span-<number>Span the specified number of rows (any positive integer).
row-span-fullSpan across all rows of the parent grid.
row-span-[<value>]Arbitrary integer row span (e.g. row-span-[5]).
row-start-<number>Start at the specified row line (any positive integer).
row-start-autoClear an inherited start line.
row-start-[<value>]Arbitrary integer start line (e.g. row-start-[3]).
row-end-<number>End at the specified row line — exclusive, per CSS grid semantics.
row-end-autoClear an inherited end line.
row-end-[<value>]Arbitrary integer end line (e.g. row-end-[7]).

Flutter’s grid renderer is built on Wrap rather than CSS Grid, so a few Tailwind v4 forms have no analogue and are intentionally unsupported:

  • Negative-prefix indices -row-<N>, -row-start-<N>, -row-end-<N> — these rely on counting back from the end of the explicit grid, a concept that doesn’t exist in the Wrap renderer.
  • Real grid cell-skippingrow-start-N and row-end-N only contribute to height via the derived span. Tiles are placed sequentially in source order, so to land an item at a specific row you fill the preceding cells with explicit placeholder tiles (as demonstrated in “Starting and ending lines” above).
  • Row-flow placementrow-* utilities only affect height in column-flow grids (grid-flow-col grid-rows-N). In the default row-flow renderer, row-span is parsed but does not change cell height; use column-flow grids when row spanning matters visually.

CSS-variable forms row-(<custom-property>), row-span-(<custom-property>), row-start-(<custom-property>), row-end-(<custom-property>) are resolved against theme-defined StyleThemeData.customProperties — e.g. row-(--my-row) behaves like row-[3] when the theme defines --my-row: '3'. Cascade-inherited or JS-set CSS variables remain out of scope.