Design System · 7 of 25
Layout
Structured layouts with consistent alignment, spacing and containers.
Layout philosophy
Layout should guide the eye and respect the user.
The best layouts feel effortless — everything has its place, the eye knows where to go next, and the design feels balanced whether on a phone or a television. A predictable layout system uses containers to set boundaries, a scale for consistent spacing, and deliberate alignment choices so the same pattern works everywhere.
The key is to avoid arbitrary pixel values and instead reach for the tokens the system already provides. That way, when you need to add a new page or adjust an existing one, you spend less time fighting the layout and more time on the content.
Rules
Use containers to bound prose and restrict measure.
Stick to the spacing scale — no magic numbers.
Choose alignment based on the relationship between items.
Test at every breakpoint before marking done.
Content stays readable across screen sizes; the container shrinks and grows deliberately.
Stack: vertical, horizontal, nested
The three basic stack directions.
A stack is a flex-direction: column or row. Use vertical when items should top-to-bottom (forms, lists). Use horizontal when items should side-by-side (action bars, tags). Use nested stacks for complex regions (sidebar + content, header with nav, masthead). Always provide a fallback — on narrow screens, a horizontal stack should become vertical.
Prefer gap over adding margins to children in flex/grid containers.
Examples
Vertical stack: form fields, list of items, vertically centered content
Horizontal stack: tag chips, action buttons, pagination controls
Nested stack: sidebar + main content header with nav
Rules
Always provide a responsive fallback (column → row at breakpoint).
Use
gapinstead of margins on flex children.Keep the stack direction consistent within a region.
Never rely on margins alone for stack layout.
The three stack directions and how they compose into regions.
Alignment
How items position within their container.
Alignment determines the horizontal or vertical position of items within a flex or grid container. The six options are: start / center / end / stretch for the main axis, and start / center / end / stretch for the cross axis. Choose the option that reflects the relationship between the items.
When in doubt, start (left / top) is the safest default. Center should be reserved for things that are meant to be focal points. End is useful for action bars and meta information.
Examples
Form labels left-aligned, inputs left-aligned
Pagination centered
Tag chips start-aligned with wrapping
Hero image stretch to fill width
Rules
Start (left / top) is the safest default for most content.
Reserve center for focal points: hero images, taglines, errors.
Use end for action bars, meta, and secondary actions.
Stretch should be deliberate — not the default for every item.
Be consistent: all form labels align the same way.
Six alignment options across main and cross axes.
Grid & containers
12-column grid with consistent gutters and responsive breakpoints.
A 12-column grid provides enough flexibility for most layouts while staying simple enough to maintain. Combine with the spacing scale for gutters, and pair with container max-widths for readable measure. The grid responds to breakpoints defined as tokens — typically sm, md, lg, xl — where columns change, gutters change, and containers change.
Use containers to bound the grid and restrict measure. The grid should rarely be used inside a container wider than its max-width.
Examples
One column: full width on mobile, fraction on desktop
Two columns: col-6 on desktop, full width on mobile
Three columns: col-4 on desktop, two columns on tablet, one on mobile
Hero image: stretch across full width with inset gutter
Rules
Define breakpoints as tokens, not raw pixel values.
Use the spacing scale for all grid-related spacing.
Limit grid use to 12 columns maximum.
Always pair with a container for measure control.
Never nest grids unnecessarily — use stacks instead.
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--space-4);
}
@media (min-width: var(--breakpoint-md)) {
.grid {
grid-template-columns: repeat(8, 1fr);
}
}
@media (min-width: var(--breakpoint-lg)) {
.grid {
grid-template-columns: repeat(12, 1fr);
}
}
.container {
max-width: 1280px;
margin-inline: auto;
padding-inline: var(--space-4);
}
@media (min-width: var(--breakpoint-md)) {
.container {
padding-inline: var(--space-6);
}
}
@media (min-width: var(--breakpoint-lg)) {
.container {
padding-inline: var(--space-8);
}
}Column spanning with consistent gutters creates aligned layouts.
Responsive layout
See the dedicated <a href="/design-system/responsive">Responsive design</a> chapter for the full strategy.
Responsive layout is about changing columns, order, and chrome at the points where the design demands it. The <a href="/design-system/responsive">Responsive design</a> chapter covers the strategy (break where content breaks, prefer auto-fit/minmax, fewer breakpoints, mobile-first, never hide primary actions), breakpoints as tokens, fluid values with clamp(), container queries, touch targets, and testing.
Rules
Break where the layout breaks, not where a device happens to be.
Prefer
auto-fitandminmaxgrids so the layout responds without named breakpoints.Fewer breakpoints is better.
Mobile-first: base styles target the narrow case, then widen.
Never hide the primary action on a small screen.
Practical guidelines
Tips for applying the layout system.
Start with the stacking direction that matches the content, then add the container and grid. Use gap instead of margins, and always test at every breakpoint. In CSS, prefer logical properties and use rem units for scalability.
Do
Use vertical stack as default. Add container for measure. Test at breakpoints. Use gap over margins.
Don't
Don't use random pixel values. Don't hide primary actions on small screens. Don't skip the responsive fallback.
Rules
Use vertical stack as the default direction.
Add container for measure, then grid for alignment.
Prefer gap over margins on flex/grid children.
Test at every breakpoint before marking done.
Responsive fallback: column → row at the breakpoint.
Keep the primary action available on all screens.
Consider touch targets (minimum 44x44px) when stacking horizontally.
// Section component using layout tokens
export function Section({ heading, children }: { heading: string; children: React.ReactNode }) {
return (
<section className="section" style={{
padding: "var(--space-8)",
display: "flex",
flexDirection: "column",
gap: "var(--space-6)",
maxWidth: "1280px",
marginInline: "auto"
}}>
{heading && <h2 style={{ marginBottom: "var(--space-4)" }}>{heading}</h2>}
{children}
</section>
);
}Checklist
Verify your layout implementation.
Structure
Container bounds the content. Stack direction matches intent. Gap used instead of margins.
Responsive
Breakpoints defined as tokens. Layout adapts across screen sizes. Primary action stays available.
Alignment
Alignment choice matches the relationship between items. Consistent across the product.
Grid
12-column grid used where appropriate. Gutters from spacing scale. Nesting avoided when stack works.