# Grid

> A responsive grid — autofit by default, or a fixed column count.

URL: https://apogee.avaui.dev/docs/grid
Last updated: 2026-10-15

A responsive grid — autofit by default, or a fixed column count.

Last updated October 15, 2026

Layout primitive — exempt from Do/Don’t and Content (no misuse or wording surface).

```astro
<Grid minItemWidth="10rem" gap={4}>
<div class="rounded-md border border-neutral p-4 text-sm">1</div>
<div class="rounded-md border border-neutral p-4 text-sm">2</div>
<div class="rounded-md border border-neutral p-4 text-sm">3</div>
<div class="rounded-md border border-neutral p-4 text-sm">4</div>
</Grid>
```

## Add

```sh
npx @ava-ui/apogee add grid
```

No Apogee dependencies.

## Usage

```astro
---
import Grid from '@/components/apogee/Grid/Grid.astro'
---
<Grid>
  <Card />
  <Card />
  <Card />
</Grid>
```

## API

`@composable` — exposed to Content Editors in AVA. Any other attribute passes through to the root `<div>`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `minItemWidth` | `string` | `'16rem'` | Autofit mode: the smallest a column may get before the count drops. Ignored when `cols` is set. |
| `cols` | `1 … 12 \| 'auto'`, responsive | — | Fixed column count (overrides autofit). `{ base: 1, md: 3 }` for breakpoints. |
| `gap` | `0 … 6 \| 8 \| 10 \| 12 \| 16`, responsive | `6` | Gap size (Tailwind `gap-*` scale). |
| `colGap` / `rowGap` | `0 \| 1 \| 2 \| 3 \| 4 \| 6 \| 8 \| 10 \| 12` | — | Gap on one axis. |
| `align` | `'start' \| 'center' \| 'end' \| 'stretch'` | — | Vertical alignment of items in their cells. |
| `justify` | `'start' \| 'center' \| 'end' \| 'stretch'` | — | Horizontal alignment of items in their cells. |
| `as` | `string` | `'div'` | Tag to render. |
| `class` | `string` | — | Extra classes, merged last. |

## GridItem

Spans columns or rows; `colSpan` and `rowSpan` accept per-breakpoint objects.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `colSpan` | `1 … 12 \| 'full'`, responsive | — | Columns to span. |
| `rowSpan` | `1 … 6`, responsive | — | Rows to span. |
| `colStart` | `1 … 13` | — | Column line to start at. |
| `rowStart` | `1 … 7` | — | Row line to start at. |
| `as` | `string` | `'div'` | Tag to render. |

```astro
<Grid cols={{ base: 1, md: 3 }} gap={4}>
<GridItem colSpan={{ base: 'full', md: 2 }}>Main</GridItem>
<GridItem>Aside</GridItem>
<GridItem colSpan="full">Footer</GridItem>
</Grid>
```

## Variants

Autofit (default) — columns reflow to the grid’s width, no breakpoints:

```astro
<Grid minItemWidth="8rem">
<div class="rounded-md border border-neutral p-4 text-sm">A</div>
<div class="rounded-md border border-neutral p-4 text-sm">B</div>
<div class="rounded-md border border-neutral p-4 text-sm">C</div>
<div class="rounded-md border border-neutral p-4 text-sm">D</div>
<div class="rounded-md border border-neutral p-4 text-sm">E</div>
</Grid>
```

Fixed columns (`cols` overrides autofit):

```astro
<Grid cols={3}>
<div class="rounded-md border border-neutral p-4 text-sm">1</div>
<div class="rounded-md border border-neutral p-4 text-sm">2</div>
<div class="rounded-md border border-neutral p-4 text-sm">3</div>
</Grid>
```

Every `gap` value (two columns, so the gap is easy to compare):

```astro
<div class="flex w-full flex-col gap-6">
<Grid cols={2} gap={0}>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=0</div>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=0</div>
</Grid>
<Grid cols={2} gap={2}>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=2</div>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=2</div>
</Grid>
<Grid cols={2} gap={4}>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=4</div>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=4</div>
</Grid>
<Grid cols={2} gap={6}>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=6</div>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=6</div>
</Grid>
<Grid cols={2} gap={8}>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=8</div>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=8</div>
</Grid>
<Grid cols={2} gap={10}>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=10</div>
  <div class="rounded-md border border-neutral p-3 text-xs">gap=10</div>
</Grid>
</div>
```

## Alignment

`align` places items vertically in their cells; `stretch` fills the cell height.

```astro
<p class="text-sm text-neutral-faded">align="start"</p>
<Grid cols={3} gap={2} align="start" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
<p class="text-sm text-neutral-faded">align="center"</p>
<Grid cols={3} gap={2} align="center" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
<p class="text-sm text-neutral-faded">align="end"</p>
<Grid cols={3} gap={2} align="end" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
<p class="text-sm text-neutral-faded">align="stretch"</p>
<Grid cols={3} gap={2} align="stretch" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
```

`justify` places items horizontally in their cells; `stretch` fills the cell width.

```astro
<p class="text-sm text-neutral-faded">justify="start"</p>
<Grid cols={3} gap={2} justify="start" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
<p class="text-sm text-neutral-faded">justify="center"</p>
<Grid cols={3} gap={2} justify="center" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
<p class="text-sm text-neutral-faded">justify="end"</p>
<Grid cols={3} gap={2} justify="end" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
<p class="text-sm text-neutral-faded">justify="stretch"</p>
<Grid cols={3} gap={2} justify="stretch" class="h-20 rounded-md border border-dashed border-neutral p-2"><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">A</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">B</div><div class="rounded-sm bg-primary-faded px-2 py-1 text-sm text-primary">C</div></Grid>
```

## Accessibility

Native semantics, no extra ARIA needed. A `<div class="grid">` carries no implicit role — if the children form a meaningful list, use a list element (`ul`/`ol`) inside or around it as appropriate.

## Tokens

No CSS custom properties. Column width comes from an inline `grid-template-columns` (computed from `minItemWidth` or `cols`); gap comes from Tailwind’s built-in `gap-*` spacing scale, not a bespoke token.

## Related

[

StackLays children out in a column or row with a consistent gap — the default way to space a group of elements.

](https://apogee.avaui.dev/docs/stack)[

BoxThe layout primitive. Direction, gap, padding, surface, border, radius and shadow as token props.

](https://apogee.avaui.dev/docs/box)[

ContainerCenters content at a max width with fluid side gutters.

](https://apogee.avaui.dev/docs/container)
