Guidelines

Layout

Every block sits on one fluid grid: 4 columns on a phone, 8 on a tablet, 12 from 990px. Gutters and section spacing grow with the screen, so a block never needs its own breakpoints for rhythm.

The grid

Set in packages/design-system/frontend.config.json and written to :root by A17's Setup plugin: --grid-columns, --inner-gutter (between columns) and --outer-gutter (the page margin). They change at Tailwind's breakpoints, so md: and lg: line up with the grid.
BreakpointFromColumnsInner gutterOuter gutter
xs0px416px20px
sm544px424px32px
md650px832px40px
lg990px1240px40px
xl1300px1240px40px
xxl1520px1248px56px

Tailwind breakpoints: sm 544px, md 650px, lg 990px, xl 1300px, xxl 1520px.

grid-layout

grid-layout lays out --grid-columns columns with --inner-gutter between them. Resize the window: the twelve cells wrap to three rows of four on a phone and two rows of eight on a tablet.
1
2
3
4
5
6
7
8
9
10
11
12
col-span-full lg:col-span-8
col-span-full lg:col-span-4
col-span-4
col-span-4
col-span-4
A hero and a card row: spans change with the column count
<section className="px-outer-gutter py-outer-2">
  <div className="grid-layout gap-y-gutter">
    <h2 className="f-h2 col-span-full lg:col-span-8">Selected work</h2>
    <p className="f-p-md col-span-full lg:col-span-4">…</p>
  </div>
</section>

Column widths

w-cols-N sizes an element to N columns plus the gutters between them, without a grid parent. It reads --container-grid-columns, falling back to --grid-columns; the demo below pins it to 12. From A17's Layout plugin, with ml-cols-N and pl-cols-N to offset.
w-cols-3
w-cols-6
w-cols-9
w-cols-12
ml-cols-3 w-cols-6

Outer gutter, container, breakout

px-outer-gutter gives a full-width section its page margin. container centres content inside the outer gutter; a breakout child escapes to the full viewport width, for a full-bleed image inside a contained block. Both are in styles/system/container.css.
Content
px-outer-gutter: the shaded band is the gutter
<section className="container py-outer-1">
  <h2 className="f-h2">Raíces</h2>
  <div className="breakout">
    {/* full-bleed, edge to edge */}
    <Image alt="…" src={cover} />
  </div>
</section>

Section spacing

Vertical rhythm between sections comes from three spacing groups in frontend.config.json, as py-, pt- and pb- utilities. outer-1 separates big moments, outer-2 is the default section, outer-3 sits between related blocks.
Fromouter-1outer-2outer-3
0px64px48px32px
650px80px64px40px
990px96px80px48px
1300px128px96px64px
spacing-outer-1
py-outer-1
spacing-outer-2
py-outer-2
spacing-outer-3
py-outer-3

Design frames

The frames designs start from in Figma, as tokens.json records them. The CSS grid above is what ships; the frames set the sizes the type scale is tuned at.
FrameDeviceWidthColumnsInner gutterOuter gutter
xsmobile390px48px14px
xltablet1024px616px16px
xxldesktop1920px12128px14px

Rules

  • Every section starts with px-outer-gutter (or container) and a py-spacing-outer-* step. No one-off section padding.
  • Lay out on bw-grid with col-span-* and gap-gutter, or size with w-cols-N. Don't hand-pick gaps between columns.
  • Full-bleed images use breakout inside a container; they don't fight the gutter with negative margins.
  • Design at the three frames (390, 1024, 1920) and check the in-betweens: the grid changes at 544, 650, 990, 1300 and 1520.