Default (auto-fit, cell-min 16rem)

Cell 1
Cell 2
Cell 3
Cell 4
Cell 5
Cell 6

data-cols="3" (max 3 columns)

A
B
C
D
E
F

data-cols="4" tight gap

1
2
3
4
5
6
7
8

  
/*
 * Grid-layout — section
 *
 * N-column grid that adapts via auto-fit + minmax. Container-aware:
 * the cell-min token controls when columns merge as the container
 * shrinks. data-cols pins a maximum column count.
 *
 *   <section class="grid-layout">
 *     <div>Cell 1</div>
 *     <div>Cell 2</div>
 *     <div>Cell 3</div>
 *   </section>
 *
 *   <section class="grid-layout" data-cols="4">
 *     <!-- max 4 cols, auto-collapse below -->
 *   </section>
 */

@layer malevich.components {
  .grid-layout {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(var(--grid-layout-cell-min), 1fr));
    gap: var(--space-gap-blocks-m);

    padding-block: var(--space-inset-section-m);
    padding-inline: var(--space-inset-section-m);

    inline-size: 100%;
    box-sizing: border-box;
  }

  /* data-cols pins a MAX column count by combining auto-fit with a
   * larger min via the standard "grid-line-trick": specifying a
   * second column-template-columns with explicit fr. We use the
   * simpler pattern: data-cols overrides the auto-fit with explicit
   * grid-template-columns above the cell-min, falls back below.
   */

  .grid-layout[data-cols="2"] {
    grid-template-columns: repeat(auto-fit, minmax(max(var(--grid-layout-cell-min), calc(50% - var(--space-gap-blocks-m))), 1fr));
  }

  .grid-layout[data-cols="3"] {
    grid-template-columns: repeat(auto-fit, minmax(max(var(--grid-layout-cell-min), calc(33.33% - var(--space-gap-blocks-m))), 1fr));
  }

  .grid-layout[data-cols="4"] {
    grid-template-columns: repeat(auto-fit, minmax(max(var(--grid-layout-cell-min), calc(25% - var(--space-gap-blocks-m))), 1fr));
  }

  .grid-layout[data-cols="6"] {
    grid-template-columns: repeat(auto-fit, minmax(max(var(--grid-layout-cell-min), calc(16.66% - var(--space-gap-blocks-m))), 1fr));
  }

  /* Gap variants */
  .grid-layout.-tight {
    gap: var(--space-gap-elements-m);
  }

  .grid-layout.-loose {
    gap: var(--space-gap-sections-s);
  }
}
This component is pure CSS — no JavaScript required.
# Grid-Layout — AGENTS.md

> Auto-generated from `grid-layout.docs.md` + the modifier applicability matrix.
> Edit those source files; this file regenerates on build.

## Identity

- **Component:** `grid-layout`
- **Layer:** sections
- **Status:** stable
- **Last updated:** 2026-05-19

## Summary

- Card grids, feature grids, pricing tables.

## Variants

| Variant | Behavior |
|---------|----------|
| Default | `auto-fit` cells of min 16rem |
| `data-cols="2"` | Up to 2 columns |
| `data-cols="3"` | Up to 3 columns |
| `data-cols="4"` | Up to 4 columns |
| `data-cols="6"` | Up to 6 columns |
| `.-tight` | Compact gap |
| `.-loose` | Larger gap |

## Modifier applicability

Per ADR-0007. Modifiers attach via `data-{category}="value"` attributes.

| Category | Accepts |
|---|---|
| `background` | — |
| `surface` | — |
| `effect` | — |
| `shader` | — |
| `rhythm` | `compact`, `regular`, `spacious` |
| `motion` | any value |
| `behavior` | — |

## Anatomy

```html
<!-- Auto-fit: cells reflow based on container width -->
<section class="grid-layout">
  <article>Cell 1</article>
  <article>Cell 2</article>
  <article>Cell 3</article>
</section>

<!-- Max 4 columns -->
<section class="grid-layout" data-cols="4">
  <!-- ... -->
</section>
```

## Tokens consumed

- `--space-gap-blocks-m` — default gap
- `--space-gap-elements-m` — tight gap
- `--space-gap-sections-s` — loose gap
- `--space-inset-section-m` — outer padding

### Component-tier (generated)
- `--grid-layout-cell-min` (16rem) — minimum cell width