Skip to content
Monogem

Layout

Overview

Layout is where Grids and Spacing meet the page: how wide content gets before it's capped and centered (containers), and the handful of shapes most screens are built from (page structure). Like Spacing, this foundation ships no new tokens — every value a container needs is already on Grids' breakpoint ladder or the master scale.

Principles

  • Containers cap, they don't invent. A container's max-width and padding reuse Grids' and Spacing's existing tokens — nothing here is a new number.
  • Name the shapes. A handful of named patterns (app shell, narrow form...) give a shared vocabulary so new pages don't each reinvent structure from scratch.
  • Cap prose for readability, not everything. Long-form text gets a measure cap; containers in general don't need one.
  • Restraint. Four named patterns, not an exhaustive taxonomy.

Tokens

This foundation adds none. It reuses:

NeedReusesFrom
Container max-width--breakpoint-sm/md/lg/xl/2xlGrids
Container side padding--scale-4 (below md) / --scale-6 (md and up)Grids' gutter recipe
.container {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--scale-4);
}
@media (min-width: 48rem) { /* --breakpoint-md */
  .container { padding-inline: var(--scale-6); max-width: var(--breakpoint-md); }
}
@media (min-width: 64rem) { .container { max-width: var(--breakpoint-lg); } }
@media (min-width: 80rem) { .container { max-width: var(--breakpoint-xl); } }
@media (min-width: 96rem) { .container { max-width: var(--breakpoint-2xl); } }

Named page patterns

PatternShapeUse for
Centered contentSingle container, vertical stack, generous top/bottom spacingMarketing pages, articles
App shellFixed-width sidebar + fluid main content area, persistent top barDashboards, admin tools
Narrow formContainer capped well below lg, single column, centered verticallySign-in, sign-up, single-task flows
Full-bleed sectionContent ignores the container, spans the full viewport widthHero banners, dividers, image bands

Rationale

Why does a container's max-width reuse --breakpoint-* instead of its own tokens? A container that caps at exactly the breakpoint it was triggered by never exceeds the viewport it targets — and that's the same number shadcn/Tailwind's own container utility already uses. A separate --container-max-md at the identical value would be duplication with zero new information, the same trap Spacing avoided with --space-md.

Why does container padding reuse Grids' gutter recipe instead of its own ladder? A container's edge padding and a grid's gutter solve the same problem — breathing room between content and the viewport edge. One recipe, tuned once, beats two that can silently drift apart.

Why four named patterns, not a general layout system? These are the shapes that recur across real products. Naming them ("this is an app shell") gives new pages a shared vocabulary without inventing a layout-engine abstraction a handful of named recipes doesn't yet need.

Why is the prose-readability cap guidance, not a token? ch is a font-relative unit with no place on this system's rem/px-based scale, and the rule only applies to long-form text — not every container. Turning it into a token would overstate it as system-wide when it's a targeted rule of thumb.

Do / Don’t

Do

  • Cap a container's width at the matching --breakpoint-* value — never a bespoke max-width.
  • Reuse Grids' two-step gutter recipe for container padding.
  • Name the page's structure when building it ("this is an app shell") so the next page matches.
  • Cap long-form prose around 65–75 characters (max-width: 65ch) for readability.

Don’t

  • Invent a --container-max-* or --container-padding-* token — reference Grids' and Spacing's existing tokens (Restraint).
  • Apply the prose-width cap to every container — it's for long-form text, not layout in general.
  • Build a fifth page-structure pattern before a real, repeated need shows up.