Grid
Flexible grid layout. Children separated by horizontal rules (---) become cells arranged in a responsive CSS grid. Supports explicit column spans, auto-fill mode, masonry, aspect ratio enforcement, and responsive collapse.
Basic usage
Equal columns created by separating content with horizontal rules.
{% grid %}
**First column.** This content sits in the first cell of the grid layout.
---
**Second column.** Grid cells are separated by horizontal rules in the Markdown source.
---
**Third column.** The grid automatically distributes available space across columns.
{% /grid %}<section data-rune="grid">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">First column.</strong>
This content sits in the first cell of the grid layout.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Second column.</strong>
Grid cells are separated by horizontal rules in the Markdown source.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Third column.</strong>
The grid automatically distributes available space across columns.
</p>
</div>
</div>
</section>First column. This content sits in the first cell of the grid layout.
Second column. Grid cells are separated by horizontal rules in the Markdown source.
Third column. The grid automatically distributes available space across columns.
<section class="rf-grid rf-grid--columns" data-mode="columns" data-rune="grid" data-density="full">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">First column.</strong>
This content sits in the first cell of the grid layout.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Second column.</strong>
Grid cells are separated by horizontal rules in the Markdown source.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Third column.</strong>
The grid automatically distributes available space across columns.
</p>
</div>
</div>
</section>Unequal columns
Use the spans attribute to control column widths. Values are space-separated span sizes.
{% grid spans="2 1" %}
**Wide column.** This column spans two units of the grid, taking up twice the space of the narrow column beside it.
---
**Narrow column.** This column takes one unit.
{% /grid %}<section data-rune="grid">
<div data-layout="grid">
<div data-colspan="2" data-name="cell">
<p>
<strong marker="**">Wide column.</strong>
This column spans two units of the grid, taking up twice the space of the narrow column beside it.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Narrow column.</strong>
This column takes one unit.
</p>
</div>
</div>
</section>Wide column. This column spans two units of the grid, taking up twice the space of the narrow column beside it.
Narrow column. This column takes one unit.
<section class="rf-grid rf-grid--columns" data-mode="columns" data-rune="grid" data-density="full">
<div data-layout="grid">
<div data-colspan="2" data-name="cell">
<p>
<strong marker="**">Wide column.</strong>
This column spans two units of the grid, taking up twice the space of the narrow column beside it.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Narrow column.</strong>
This column takes one unit.
</p>
</div>
</div>
</section>Gap
Control spacing between cells with the gap attribute.
{% grid gap="tight" %}
**Tight gap.** Less space between cells.
---
**Second cell.** The gap is smaller than default.
---
**Third cell.** Useful for compact layouts.
{% /grid %}<section data-rune="grid">
<meta content="tight" data-field="gap">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Tight gap.</strong>
Less space between cells.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Second cell.</strong>
The gap is smaller than default.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Third cell.</strong>
Useful for compact layouts.
</p>
</div>
</div>
</section>Tight gap. Less space between cells.
Second cell. The gap is smaller than default.
Third cell. Useful for compact layouts.
<section class="rf-grid rf-grid--columns" data-mode="columns" data-gap="tight" data-rune="grid" data-density="full" style="--grid-gap: var(--rf-spacing-sm)">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Tight gap.</strong>
Less space between cells.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Second cell.</strong>
The gap is smaller than default.
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Third cell.</strong>
Useful for compact layouts.
</p>
</div>
</div>
</section>Alignment
Vertically align cells within their row using the valign attribute. Useful when cells have different heights.
{% grid valign="center" spans="2 1" %}
**Tall cell.** This cell has more content and takes up more vertical space. The adjacent cell will be vertically centred relative to this one.
Additional paragraph to increase the height of this cell.
---
**Centred.** This shorter cell is vertically centred.
{% /grid %}<section data-rune="grid">
<meta content="center" data-field="valign">
<div data-layout="grid">
<div data-colspan="2" data-name="cell">
<p>
<strong marker="**">Tall cell.</strong>
This cell has more content and takes up more vertical space. The adjacent cell will be vertically centred relative to this one.
</p>
<p>Additional paragraph to increase the height of this cell.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Centred.</strong>
This shorter cell is vertically centred.
</p>
</div>
</div>
</section>Tall cell. This cell has more content and takes up more vertical space. The adjacent cell will be vertically centred relative to this one.
Additional paragraph to increase the height of this cell.
Centred. This shorter cell is vertically centred.
<section class="rf-grid rf-grid--columns" data-mode="columns" data-valign="center" data-rune="grid" data-density="full" style="--grid-valign: center">
<div data-layout="grid">
<div data-colspan="2" data-name="cell">
<p>
<strong marker="**">Tall cell.</strong>
This cell has more content and takes up more vertical space. The adjacent cell will be vertically centred relative to this one.
</p>
<p>Additional paragraph to increase the height of this cell.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<strong marker="**">Centred.</strong>
This shorter cell is vertically centred.
</p>
</div>
</div>
</section>Responsive collapse
Force the grid to collapse to a single column at a given breakpoint.
{% grid collapse="md" %}
Sidebar content.
---
Main content.
{% /grid %}
Breakpoints: sm (640px), md (768px), lg (1024px), or never.
Auto mode
Responsive auto-fill layout. The grid creates as many columns as fit, each at least min wide. No explicit column count needed.
{% grid mode="auto" min="200px" %}
Card one.
---
Card two.
---
Card three.
---
Card four.
{% /grid %}<section data-rune="grid">
<meta content="auto" data-field="mode">
<meta content="200px" data-field="min">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>Card one.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>Card two.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>Card three.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>Card four.</p>
</div>
</div>
</section>Card one.
Card two.
Card three.
Card four.
<section class="rf-grid rf-grid--auto" data-mode="auto" data-min="200px" data-rune="grid" data-density="full" style="--grid-min: 200px">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>Card one.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>Card two.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>Card three.</p>
</div>
<div data-colspan="1" data-name="cell">
<p>Card four.</p>
</div>
</div>
</section>Masonry mode
Progressive enhancement for masonry-style layouts. Falls back to a standard grid in browsers that don't support CSS masonry.
{% grid mode="masonry" columns=3 %}
Short card.
---
A taller card with more content that takes up more vertical space.
---
Medium card.
---
Another short one.
{% /grid %}
Aspect ratio
Enforce a uniform aspect ratio on all grid cells. Content is cropped with object-fit: cover — ideal for image galleries.
{% grid mode="auto" min="200px" aspect="1/1" %}

---

---

---

{% /grid %}<section data-rune="grid">
<meta content="auto" data-field="mode">
<meta content="200px" data-field="min">
<meta content="1/1" data-field="aspect">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid1/400/400" alt="">
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid2/400/400" alt="">
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid3/400/400" alt="">
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid4/400/400" alt="">
</p>
</div>
</div>
</section><section class="rf-grid rf-grid--auto" data-mode="auto" data-aspect="1/1" data-min="200px" data-rune="grid" data-density="full" style="--grid-min: 200px; --grid-aspect: 1/1">
<div data-layout="grid">
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid1/400/400" alt="" />
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid2/400/400" alt="" />
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid3/400/400" alt="" />
</p>
</div>
<div data-colspan="1" data-name="cell">
<p>
<img src="https://picsum.photos/seed/grid4/400/400" alt="" />
</p>
</div>
</div>
</section>Stack order
Control the order of cells when the grid collapses to a single column on mobile. By default cells stack in source order; stack="reverse" places the last cell first.
{% grid spans="2 1" collapse="md" stack="reverse" %}
Main content (appears second on mobile).
---
Sidebar (appears first on mobile).
{% /grid %}
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
columns | number | — | Fixed number of grid columns |
rows | number | — | Fixed number of grid rows |
flow | string | — | Grid flow: row, column, dense, row dense, column dense |
spans | string | — | Space-separated column span values (e.g., "2 1") |
ratio | string | — | Column width ratio as CSS grid-template-columns value |
gap | string | default | Gap between cells: none, tight, default, or loose |
valign | string | — | Vertical cell alignment: top, center, or bottom |
collapse | string | — | Collapse to single column at breakpoint: sm, md, lg, or never |
mode | string | columns | Layout mode: columns, auto, or masonry |
min | string | 250px | Minimum column width in auto mode (e.g., 200px, 15rem) |
aspect | string | — | Aspect ratio enforced on all cells (e.g., 16/9, 1/1) |
stack | string | — | Cell order when collapsed: natural or reverse |
Common attributes
All block runes share these attributes for layout and theming.
| Attribute | Type | Default | Description |
|---|---|---|---|
width | string | content | Page grid width: content, wide, or full |
spacing | string | — | Vertical spacing: flush, tight, default, loose, or breathe |
inset | string | — | Horizontal padding: flush, tight, default, loose, or breathe |
tint | string | — | Named colour tint from theme configuration |
tint-mode | string | auto | Colour scheme override: auto, dark, or light |
bg | string | — | Named background preset from theme configuration |