Fluid page/section spacing vs. Tailwind's fixed scale for component internals, plus the layout primitives.

Last updated

Two different spacing systems, deliberately not unified:

  • Page/section rhythm — fluid clamp() tokens, so gutters and vertical spacing scale smoothly with the viewport.
  • Component internals — Tailwind’s fixed numeric scale (p-2, gap-4), so a button’s own padding doesn’t stretch as the window resizes.

Fluid layout tokens

Token Value Utility Used for
--spacing-gutter clamp(1rem, 0.55rem + 2.25vw, 2rem) px-gutter Page side padding
--spacing-section-sm clamp(2rem, 1.4rem + 3vw, 3.5rem) py-section-sm Tight vertical rhythm
--spacing-section clamp(3rem, 2rem + 5vw, 6rem) py-section Default section rhythm
--spacing-section-lg clamp(4rem, 2.57rem + 4.76vw, 6rem) py-section-lg Generous vertical rhythm
--spacing-section-xl clamp(5rem, 3rem + 10vw, 12rem) py-section-xl Hero / feature rhythm

Container applies px-gutter directly for its side padding. Section’s space prop maps straight onto these fluid tokens — sm → py-section-sm, md → py-section, lg → py-section-lg, xl → py-section-xl — so a section breathes with the viewport. Use the py-section* utilities directly in custom markup for the same rhythm without the component.

Component internals: the fixed scale

Inside a component, keep Tailwind’s ordinary numeric spacing (p-2, gap-4, px-3) — never the fluid tokens. A control’s own padding shouldn’t resize with the viewport; only page-level layout should.

<!-- page rhythm: fluid -->
<section class="px-gutter py-section">...</section>

<!-- component internals: fixed -->
<button class="px-4 py-2 gap-2">...</button>

Layout primitives

Component Purpose Key props
Container Centers content at a max width with px-gutter side padding size (sm–xl, full), as
Section Full-width band with vertical padding, wraps a Container; theme flips tokens for the subtree space, theme, containerSize, container, as
Grid Responsive grid — autofit columns from minItemWidth by default, or a fixed cols count minItemWidth, cols, gap
Stack Flex column or row with a token gap — the workhorse for spacing groups of elements direction, gap, align, justify, wrap
One
Two
Three
Show code
<Stack direction="row" gap={4}>
<div class="rounded-md bg-neutral-faded px-4 py-3 text-sm">One</div>
<div class="rounded-md bg-neutral-faded px-4 py-3 text-sm">Two</div>
<div class="rounded-md bg-neutral-faded px-4 py-3 text-sm">Three</div>
</Stack>

Grid reflows column count to its own width — no breakpoints needed:

A
B
C
D
Show code
<Grid minItemWidth="8rem" gap={4}>
<div class="rounded-md bg-neutral-faded px-4 py-3 text-sm">A</div>
<div class="rounded-md bg-neutral-faded px-4 py-3 text-sm">B</div>
<div class="rounded-md bg-neutral-faded px-4 py-3 text-sm">C</div>
<div class="rounded-md bg-neutral-faded px-4 py-3 text-sm">D</div>
</Grid>