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" %}
![](https://picsum.photos/seed/grid1/400/400)

---

![](https://picsum.photos/seed/grid2/400/400)

---

![](https://picsum.photos/seed/grid3/400/400)

---

![](https://picsum.photos/seed/grid4/400/400)
{% /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

AttributeTypeDefaultDescription
columnsnumberFixed number of grid columns
rowsnumberFixed number of grid rows
flowstringGrid flow: row, column, dense, row dense, column dense
spansstringSpace-separated column span values (e.g., "2 1")
ratiostringColumn width ratio as CSS grid-template-columns value
gapstringdefaultGap between cells: none, tight, default, or loose
valignstringVertical cell alignment: top, center, or bottom
collapsestringCollapse to single column at breakpoint: sm, md, lg, or never
modestringcolumnsLayout mode: columns, auto, or masonry
minstring250pxMinimum column width in auto mode (e.g., 200px, 15rem)
aspectstringAspect ratio enforced on all cells (e.g., 16/9, 1/1)
stackstringCell order when collapsed: natural or reverse

Common attributes

All block runes share these attributes for layout and theming.

AttributeTypeDefaultDescription
widthstringcontentPage grid width: content, wide, or full
spacingstringVertical spacing: flush, tight, default, loose, or breathe
insetstringHorizontal padding: flush, tight, default, loose, or breathe
tintstringNamed colour tint from theme configuration
tint-modestringautoColour scheme override: auto, dark, or light
bgstringNamed background preset from theme configuration