Page Grid
The horizontal frame around every Brik page — the width-container recipe, the canonical gutter token, which content width each band gets, and the measure that caps the readable text column inside it.
Content Rhythm governs the vertical axis; this page governs the horizontal one. Every content band on a Brik page — a marketing section's container, a header, a footer, a consumer site's nav — is framed the same way: a --content-width-* band, centred, inset from the viewport edge by the canonical page gutter. One recipe, so BDS sections and consumer containers stay flush-aligned at every breakpoint (ADR-025).
The width-container recipe
Three declarations, always together:
.my-container {
max-width: var(--content-width-xl); /* the band */
margin-inline: auto; /* centred */
padding-inline: var(--gutter-page); /* the page gutter */
}--content-width-xl (1280px) is the default band — the value the section shell, SiteHeader, Footer, and the brikdesigns nav all resolve to. Narrower bands are a per-role choice from the width roles table, not a new number.
The lint-page-grid gate fails any container rule whose padding-inline bypasses --gutter-page — a container on an ad-hoc inset drifts out of alignment with every other band on the page.
Two kinds of gutter
"Gutter" names two different relationships. Only the page edge gets a dedicated token; space between columns is already governed by the component rhythm map.
| Sense | Relationship | Mechanism |
|---|---|---|
| Page gutter | Viewport edge ↔ content band | padding-inline: var(--gutter-page) on the container |
| Column gutter | Sibling ↔ sibling in a Grid or Cluster | The primitive's gap, from the --gap-* scale |
This is the gap-vs-padding rule from Content Rhythm applied horizontally: gap is between siblings, padding is the edge.
--gutter-page is a fixed alias of --padding-lg, so it re-modulates under spacing modes but does not vary with viewport width. That is deliberate: a fluid clamp() gutter misaligns consumer containers from BDS section content at intermediate widths — brikdesigns shipped one and had to walk it back. In TS, import pageGutter from @bds-tokens rather than writing the var() string inline.
Content width roles
| Token | Width | Role |
|---|---|---|
--content-width-narrow | 640px | Prose, reading columns, focused forms |
--content-width-default | 800px | Standard text-led body sections |
--content-width-wide | 1024px | Feature grids, CTA bands |
--content-width-xl | 1280px | The page band — hero, header, footer, most sections |
--content-width-full | 100% | Full-bleed; prefer an explicit width |
These are content constraints, not breakpoints — even where the pixel values coincide. For media queries use the breakpoints TS export from @bds-tokens; CSS custom properties cannot appear inside @media conditions, so the --breakpoint-* CSS variables are reference-only.
There is no responsive-spacing axis: density modes are the only spacing modulation in BDS. Do not introduce breakpoint-varying gutters or gaps.
Content measure
A band width is not a text width. --content-width-xl (1280px) sizes the band; a title or description spanning the full 1280px is unreadable. The measure is the max width of the readable text column inside the band — a separate, narrower cap applied to the text group, not to the container (ADR-032).
| Token | Width | Role |
|---|---|---|
--measure-sm | 44ch | Short intro — a single-line eyebrow + title |
--measure-md | 60ch | Section-header title + description — the default |
--measure-lg | 72ch | Long-form prose, rich-text body |
ch, not px: a measure tracks the type size, so the line stays readable if the font scales. And unlike --gap-* and --padding-*, measures are static across spacing modes — a readable line length is a typographic constant, not a density knob.
Band and measure are two different jobs — keep them separate:
| Sizes | Token family | Mechanism | |
|---|---|---|---|
| Band | The container / section width | --content-width-* | max-width + margin-inline: auto on the container |
| Measure | The text column inside it | --measure-* | max-width on the text group — usually via SectionHeader |
SectionHeader
Don't hand-roll the cap. A centered section intro — eyebrow / title / description above a card grid, a CTA band, a hero — is a SectionHeader: it composes ContentBlock for the slot rhythm (ADR-023) and adds only the measure + centering — the concern ContentBlock deliberately does not own.
<SectionHeader
title="What we do"
description="From branding to websites to behind-the-scenes systems…"
/>
// centered · measure-md (60ch) · <h2> title at heading-lg — nothing to overridemeasure (sm / md / lg, default md) picks the cap; align (center / start, default center) picks whether the column centers in the band or anchors to its start. SectionHeader never sets a band width — drop it inside the section's width-container and it caps the text within. This is the single replacement for the ad-hoc measures a section header used to be written with (600px, 700px, width: 70%, max-width: none, a reused --content-width-narrow).
A measure is not a band. Never cap a section intro with a --content-width-* token (that sizes the container) or with a raw px / percentage. Reach for SectionHeader — or --measure-* directly only when hand-rolling a text group SectionHeader doesn't cover.
Where the recipe is set
Like the rhythm scale, you rarely write the recipe by hand — it is baked into the layer that owns each surface.
- Marketing sections →
.bds-blueprint-section__container(ADR-021). Override band or inset via the section's hooks, never by hand-rolling a sibling container:
.bds-cta__container {
--bds-blueprint-section-content-width: var(--content-width-wide);
--bds-blueprint-section-padding-inline: var(--padding-xl);
}- Product apps → the
Pageprimitive; itspaddingprop sets the shell inset (lgis the page gutter). - Full-bleed backgrounds with constrained content →
Footer'scontainerMaxWidthshape: the background spans the viewport whilepadding-inline: max(var(--gutter-page), calc((100% - var(--content-width-xl)) / 2))centres the content band. - Section vertical band → unchanged from ADR-021:
padding-block: clamp(var(--padding-xl), 7vw, var(--padding-huge)). A page is a stack of full-bleed sections; the vertical band is the clamp, the horizontal band is this recipe.
Related
- Content Rhythm — the vertical axis this page mirrors.
- Page Structure — the HTML skeleton these containers live in.
- Composition Layers — the Section → Layout → Container → Block or Control → Component model.
- Spacing — the
--padding-*scale behind the gutter and the density modes that modulate it.
Banner Groups
The order, placement, and spacing rules for a surface carrying more than one banner — and the cases where the second banner is the wrong answer.
Image Sourcing
Where imagery comes from on a Brik web build — the photography-first sourcing ladder, the AI-imagery policy, and how to wire the asset into Image and Frame.