Brik Design System
Build Standards

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.

SenseRelationshipMechanism
Page gutterViewport edge ↔ content bandpadding-inline: var(--gutter-page) on the container
Column gutterSibling ↔ sibling in a Grid or ClusterThe 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

TokenWidthRole
--content-width-narrow640pxProse, reading columns, focused forms
--content-width-default800pxStandard text-led body sections
--content-width-wide1024pxFeature grids, CTA bands
--content-width-xl1280pxThe page band — hero, header, footer, most sections
--content-width-full100%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).

TokenWidthRole
--measure-sm44chShort intro — a single-line eyebrow + title
--measure-md60chSection-header title + description — the default
--measure-lg72chLong-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:

SizesToken familyMechanism
BandThe container / section width--content-width-*max-width + margin-inline: auto on the container
MeasureThe 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 override

measure (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 Page primitive; its padding prop sets the shell inset (lg is the page gutter).
  • Full-bleed backgrounds with constrained contentFooter's containerMaxWidth shape: the background spans the viewport while padding-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.
  • 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.

On this page

💬