Skip to content

Layout — Column grid

app-layout specs/app-layout/column-grid.kmd

A responsive column grid — 4 / 8 / 12 columns keyed to the M3 window-size classes, with gutter, outer margin, and a container cap for TV. Complements window-size-classes (which classes exist) and canonical-layouts (which region pattern fills them) by fixing the column substrate a layout lays regions onto. Closes the KDS×gov.br gap (govbr-ds-parity, stack#402): gov.br ships an explicit 4/8/12 column grid with a TV tier; KDS had size classes but no documented grid.

When this spec applies

Primary triggers

All triggers

Specification body

Column grid

R1 — Columns per window-size class

The grid's column count is keyed to the M3 window-size classes (window-size-classes.kmd), NOT the --kds-bp-* utility scale — so the grid and the layout response switch on the same boundaries:

ClassWidthColumnsGutterMargin
Compact< 60041616
Medium600–83981616
Expanded840–1199122424
Large≥ 1200122432

12 is the ceiling. A wider viewport gets more margin / whitespace, never more columns — matching M3 and gov.br. Margins match window-size-classes.kmd R2's container padding (16/16/24/32).

R2 — TV tier

gov.br distinguishes a TV tier; KDS folds TV into Large. At the TV sub-tier (≥ 1600) the grid stays 12 columns but the container is capped and centred (--kds-container-max: 1600px), so ultrawide/TV surfaces gain balanced side whitespace instead of over-long 12-column measures.

R3 — Container: fixed vs fluid

Below the cap the container is fluid — the 12 columns fill the available width minus the class margin. At/above the TV cap it is fixed — a centred max-width container (R2). A surface MAY opt a region into a narrower fixed measure (e.g. a reading column) without changing the page grid.

R4 — Adaptive vs stable spans

A region's column span is either adaptive — it re-spans as the class changes (e.g. a card row that is 4-of-4 on Compact, 4-of-8 on Medium, 4-of-12 on Expanded) — or stable — it holds a fixed fraction (e.g. a sidebar that is always 3-of-12 on Expanded+). Canonical region patterns (canonical-layouts.kmd) choose per region; this spec only fixes the column substrate they span.

R5 — Tokens

Published in the KDS dist tokens (assets/css/base.css :root, served at https://kds.koder.dev), overridden per class via @media at the window-size-class boundaries:

  • --kds-grid-cols — column count (4 / 8 / 12).
  • --kds-grid-gutter — inter-column gap (16 / 24).
  • --kds-grid-margin — outer page margin (16 / 24 / 32).
  • --kds-container-maxnone (fluid) below the TV cap, 1600px at/above.

Consume with display: grid; grid-template-columns: repeat(var(--kds-grid-cols), 1fr); column-gap: var(--kds-grid-gutter), padded by --kds-grid-margin. Grid margins are layout structure and are not density-scaled (unlike the --kds-space-* component spacing of spacing-scale.kmd).

R6 — Forbidden

  • ❌ Hard-coded column counts or breakpoints that bypass the window-size classes (window-size-classes.kmd R6 — no single-hardcoded-breakpoint layouts).
  • ❌ More than 12 columns at any width (widen margins, not the column count).
  • ❌ A second breakpoint system for the grid (reuse the window-size-class boundaries).

Não-escopo / follow-up

  • Adoption of the grid tokens across the landing pages and app layouts — an incremental sweep tracked separately (the tokens ship here; consumers migrate off ad-hoc grids onto --kds-grid-* per surface). See stack#447 (opened).
  • A .kds-col-grid utility class — the tokens are the contract; a vendored utility class (if added) belongs in koder_web_kit.css (the drift-gated SoT), not invented in the design-gen copy.

References