Layout grid + cards
Arrange content in columns of cards — use spatial structure to express "these items are peers; you can compare them horizontally." Useful for feature comparisons, option lists, three-way trade-offs, team / case showcases.
When to use
- ✅ N peer options for the reader to compare side by side (product tiers / pricing / tools)
- ✅ Multiple parallel features as a card grid (homepage features section)
- ✅ Triangle of arguments — objective comparison of plan A / B / C
- ✅ Team / case studies — one card per person or case
- ❌ Single block of information — use Callout
- ❌ Wildly uneven content lengths — cards become misaligned, visually broken
- ❌ Strict sequence (step 1 → 2 → 3) — use Stepper
Basic syntax
```layout grid cols=3
:::card accent=blue
**Plan A**
Short description + one or two key points.
:::
:::card accent=red
**Plan B**
Short description + one or two key points.
:::
:::card accent=green
**Plan C**
Short description + one or two key points.
:::
```
Renders: 3 equal-width cards side by side; each has a colored accent bar on top; on narrow screens, they stack into a single column automatically.
All options
Block-level: ```layout grid
| Option | Type | Default | Purpose |
|---|---|---|---|
cols |
int (1-6) | 2 |
Number of columns. Below 720px, auto-collapses to 1 column |
Card-level: :::card
| Option | Type | Default | Purpose |
|---|---|---|---|
accent |
enum | gray |
Color of the top accent bar (6 choices) |
Accent palette (6 colors):
| Value | Visual | Recommended use |
|---|---|---|
blue |
Blue | Neutral / informational / featured |
red |
Red | Warning / high-risk / not recommended |
green |
Green | Recommended / passing / success |
yellow |
Yellow | Attention / requires care |
purple |
Purple | Premium / Pro / special |
gray |
Gray | Neutral / default (omitting accent gives this) |
Examples
Example 1: 3-column product tiers
```layout grid cols=3
:::card accent=gray
**Free**
- Personal use
- 5 documents
- Community support
$0/month
:::
:::card accent=blue
**Pro**
- Personal pro
- Unlimited documents
- Email support
- Private sharing
$10/month
:::
:::card accent=purple
**Team**
- Team collaboration
- SSO + audit
- Priority support
- 99.9% SLA
$50/month
:::
```
Renders: three equal-width cards with gray / blue / purple accent bars. The Pro tier carries the strongest visual weight (blue), Team is marked "premium" (purple). Readers see the hierarchy at a glance.
Example 2: nested callout
```layout grid cols=2
:::card accent=green
**Recommended: A**
> [!INFO]
> Plan A fits 90% of users; zero-config out of the box.
Detailed explanation...
:::
:::card accent=red
**Not recommended: B**
> [!WARN]
> Plan B requires self-hosting. Advanced users only.
Detailed explanation...
:::
```
Renders: two cards, each holding a callout (INFO / WARN). The card provides layout, the callout provides semantic emphasis — distinct responsibilities.
Example 3: single column (cols=1)
```layout grid cols=1
:::card accent=blue
A full-width card — like "a paragraph with an accent bar."
:::
```
Renders: a single full-width card. Looks like a callout, but the semantics differ — this is "a grouped content block," not "a highlighted note."
Example 4: 4 columns or more
```layout grid cols=4
:::card accent=blue
Feature 1
:::
:::card accent=blue
Feature 2
:::
:::card accent=blue
Feature 3
:::
:::card accent=blue
Feature 4
:::
```
Renders: 4 equal columns. On a desktop screen, each card is ~250px wide. Above 4 columns, content gets cramped — 5/6 columns work only for icon + one-line text.
Plain-text fallback behavior
:::card is a markdown directive container (CommonMark Container Blocks proposal). In readers without directive support:
:::card accent=blue
**Plan A**
Description
:::
→ :::card accent=blue and ::: show as plain text; the markdown content inside the cards still renders (bold, lists, links, etc., all work).
Per-reader breakdown:
| Reader | Render |
|---|---|
| Rho | Full grid + cards + accent |
| GitHub web | :::card accent=blue literal + card content as standard markdown |
| Obsidian | Some plugins support it (obsidian-callout, containers); default shows literal |
| VS Code default preview | ::: literal + content as standard markdown |
| cat / less | Source as plain text |
Content remains readable in every case — only the layout visual disappears.
Common pitfalls
1. Wrong accent value
:::card accent=skyblue ← ❌ Not recognized; falls back to gray
:::card accent=BLUE ← ⚠️ Case-sensitive; lowercase recommended
:::card accent=blue ← ✅
Only six valid values: blue / red / green / yellow / purple / gray.
2. Forgot to close :::
```layout grid cols=2
:::card accent=blue
Content A
← ❌ Missing :::
:::card accent=red
Content B
:::
```
→ The whole layout block fails to parse. Every :::card needs a paired ::: to close.
3. cols mismatches the number of cards
```layout grid cols=3
:::card accent=blue
A
:::
:::card accent=red
B
:::
```
→ Two cards in a 3-column layout — the third column is empty. Doesn't error, but the visual is asymmetric. Either change to cols=2 or add a third card.
4. Severely uneven card content
```layout grid cols=2
:::card accent=blue
Plan A: very long description, 5 paragraphs, 3 lists, nested callout, code block...
:::
:::card accent=red
Plan B: one sentence.
:::
```
→ The left card is tall, the right card looks chopped. Visually broken. Fix: bring the right card up to comparable length, or use Stepper (one at a time) or Tabs.
5. Don't nest layout in layout
```layout grid cols=2
:::card
```layout grid cols=2 ← ❌ Don't nest
:::card
:::
:::card
:::
```
:::
```
→ The inner grid behavior is undefined. Layouts shouldn't nest. If you need complex structure, switch to Stepper or rethink the page.
6. Putting interact blocks inside cards — fine, but watch hydration
:::card accent=blue
```interact
slider x range=0..10 step=1 default=5
template stl:
[selected] -> [{x}]
```
:::
✅ Fully supported (see Nested DSL). But the card's height changes as the interact block renders — sliding may shift adjacent cards. Suggestion: give the interact block a fixed min-height, or place it on its own row outside the grid.
See also
- Callout — Single-passage emphasis; different semantic slot from layout
- Tabs — Same space, switchable content (saves vertical space)
- Stepper — Strict sequential walkthrough (one step at a time)
- Nested DSL — Embedding callout / interact / etc. inside layout cards
- Plain-text fallback principle