Layout & Spacing

Spacing and layout are what separate amateur designs from professional ones. Two designs can use the same fonts, colors, and components, and the one with better spacing will look dramatically better. Spacing creates visual relationships, establishes hierarchy, and makes content scannable.

The 8-Point Grid System

All spacing and sizing should be multiples of 8px. This is the most widely used grid system in modern UI design.

4px   ████                      (half-step for micro adjustments)
8px   ████████                  (smallest usable spacing)
12px  ████████████              (tight spacing, icon padding)
16px  ████████████████          (standard element spacing)
24px  ████████████████████████  (medium spacing)
32px  ████████████████████████████████  (between groups)
40px  ████████████████████████████████████████  (between sections)
48px  ████████████████████████████████████████████████  (section padding)
64px  [larger bar]              (major sections)
96px  [larger bar]              (page sections)

Why 8?

  • Divisible by 2 and 4, so half and quarter steps are whole numbers
  • Works cleanly on all screen densities (1×, 1.5×, 2×, 3×)
  • Aligns with common device dimensions
  • Wide enough that the eye can distinguish between steps (4px is hard to distinguish from 8px; 8px from 16px is clear)

When to use 4px: Icons, small badges, fine adjustments within components. Everything else should be 8px multiples.

Spacing Tokens

Don't use arbitrary pixel values. Define a spacing scale and use it everywhere:

:root {
  --space-1:   4px;    /* 0.25rem — Micro: icon internal padding */
  --space-2:   8px;    /* 0.5rem  — XS: tight gaps, inline spacing */
  --space-3:   12px;   /* 0.75rem — SM: input padding, icon+label gap */
  --space-4:   16px;   /* 1rem    — MD: default element spacing */
  --space-5:   20px;   /* 1.25rem — Between form fields */
  --space-6:   24px;   /* 1.5rem  — LG: between card content areas */
  --space-8:   32px;   /* 2rem    — XL: between groups/sections */
  --space-10:  40px;   /* 2.5rem  — Between major groups */
  --space-12:  48px;   /* 3rem    — Section padding (mobile) */
  --space-16:  64px;   /* 4rem    — Section padding (desktop) */
  --space-20:  80px;   /* 5rem    — Large section gaps */
  --space-24:  96px;   /* 6rem    — Major page sections */
}

Applying Spacing Tokens

WhereTokenSizeExample
Icon to label gapspace-28px[icon] 8px [Label Text]
Input internal paddingspace-312pxPadding inside an input field
Between form fieldsspace-520pxGap between "Name" and "Email" fields
Between card content sectionsspace-624pxGap between card title area and card body
Between content groupsspace-832pxGap between "Personal Info" and "Address" groups
Section padding (mobile)space-1248pxVertical padding of a page section
Section padding (desktop)space-16-2464-96pxVertical padding scales up on large screens

Rule of thumb: spacing within groups < spacing between groups. If elements inside a card have 16px gaps, the gap between cards should be at least 24px.

Whitespace

Why Whitespace Matters

More WhitespaceLess Whitespace
Premium, luxury feelDense, information-heavy feel
Easier to scanMore content per screen
Draws attention to contentCan overwhelm and cause decision fatigue
Apple, Stripe, LinearBloomberg Terminal, spreadsheets

Neither is inherently better. Match the whitespace level to the product's purpose.

Whitespace Guidelines

  1. Group related elements with proximity. Items that belong together should be close. Items that don't should have more space between them.
BAD (equal spacing everywhere):
Full Name          ← 24px
[___________]      ← 24px
Email              ← 24px
[___________]      ← 24px
Street Address     ← 24px
[___________]      ← 24px
City               ← 24px
[___________]

GOOD (proximity creates groups):
Full Name          ← 8px
[___________]      ← 16px
Email              ← 8px
[___________]

              ← 32px (gap = new group)

Street Address     ← 8px
[___________]      ← 16px
City               ← 8px
[___________]
  1. Increase whitespace at larger screen sizes. A 48px section gap on mobile should become 80-120px on desktop. Don't just make the content wider.

  2. Active whitespace around CTAs. Surround your primary action button with generous space so it stands out.

  3. Consistent internal vs. external spacing on components. A card should have consistent padding internally (e.g., 24px on all sides) and consistent margins externally (e.g., 16px between cards).

  4. When in doubt, add more space. Beginners use too little whitespace. Give content room to breathe.

Layout Patterns

The Container

Every page needs a centered, max-width container to prevent content from stretching across ultra-wide monitors:

.container {
  width: 100%;
  max-width: 1200px;    /* Common: 1140px, 1200px, 1280px */
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;   /* Mobile gutters */
  padding-right: 16px;
}

@media (min-width: 768px) {
  .container {
    padding-left: 24px;
    padding-right: 24px;
  }
}

@media (min-width: 1024px) {
  .container {
    padding-left: 32px;  /* Desktop gutters */
    padding-right: 32px;
  }
}
Container WidthBest For
720pxBlog/article content (narrow, focused reading)
960pxSimple marketing pages, single-column layouts
1140pxStandard web apps, Bootstrap default
1200pxCommon modern default
1280pxData-heavy apps, dashboards
1440pxWide layouts, full-width apps
100% (no max)Full-bleed designs, dashboards, apps

Card Grids

Cards are the most common content container. Use CSS Grid for responsive card layouts:

/* Auto-responsive cards — no breakpoints needed */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
}

This creates cards that are at least 300px wide and fill available space. The grid automatically adjusts the number of columns based on viewport width.

Min Card WidthResult at 1200pxBest For
200px5 columnsSmall cards, thumbnails
280px4 columnsProduct cards, previews
300px3 columnsStandard content cards
380px3 columns (wider)Feature cards, blog posts
500px2 columnsDetailed cards, case studies

Split/Two-Column Layout

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
}

@media (max-width: 768px) {
  .split {
    grid-template-columns: 1fr;   /* Stack on mobile */
    gap: 24px;
  }
}
.sidebar-layout {
  display: grid;
  grid-template-columns: 260px 1fr;    /* Fixed sidebar */
  gap: 32px;
}

@media (max-width: 768px) {
  .sidebar-layout {
    grid-template-columns: 1fr;          /* Stack on mobile */
  }
}

Common sidebar widths:

WidthUse Case
200-240pxNarrow sidebar, icon + short labels
260-280pxStandard sidebar, comfortable text labels
300-320pxWide sidebar, sidebar with nested items
360-400pxVery wide, settings panel or secondary content

Holy Grail Layout

Header plus sidebar plus main plus footer, the classic app layout:

.app-layout {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 260px 1fr;
  min-height: 100vh;
}

.header  { grid-column: 1 / -1; }  /* Full width */
.sidebar { grid-row: 2; }
.main    { grid-row: 2; overflow-y: auto; }
.footer  { grid-column: 1 / -1; }  /* Full width */

Stack Layout

The simplest pattern: vertically stacked elements with consistent spacing:

.stack > * + * {
  margin-top: 16px;   /* Consistent gap between all children */
}

/* Or with gap (no margin collapsing issues) */
.stack {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

Responsive Spacing

Spacing should scale with screen size. Mobile screens need tighter spacing to fit content; desktop screens need looser spacing to avoid vast empty areas.

Approach 1: Breakpoint-Based Tokens

:root {
  --section-padding: 48px;
  --card-gap: 16px;
  --container-gutter: 16px;
}

@media (min-width: 768px) {
  :root {
    --section-padding: 80px;
    --card-gap: 24px;
    --container-gutter: 24px;
  }
}

@media (min-width: 1200px) {
  :root {
    --section-padding: 120px;
    --card-gap: 32px;
    --container-gutter: 32px;
  }
}

Approach 2: Fluid Spacing with clamp()

:root {
  --section-padding: clamp(48px, 8vw, 120px);
  --card-gap: clamp(16px, 2vw, 32px);
  --container-gutter: clamp(16px, 3vw, 48px);
}

Responsive Spacing Scale

TokenMobile (< 768px)Tablet (768-1023px)Desktop (1024px+)
Element gap8-16px16px16px
Group gap16-24px24-32px32px
Section padding32-48px64-80px80-120px
Page margins16px24px32-48px

The Spacing Relationship Hierarchy

Space communicates relationships. Use this hierarchy consistently:

TIGHTEST SPACING → LOOSEST SPACING

Within a component     →  Between components  →  Between groups  →  Between sections
(8-16px)                  (16-24px)              (24-48px)          (48-120px)

Example:
┌─────────────────────────────────┐
│ Card Title           ← 8px     │ ← Within component
│ Card subtitle        ← 16px   │
│ Card body text...    ← 24px   │
│ [Action Button]                │
└─────────────────────────────────┘
                       ← 24px     ← Between components
┌─────────────────────────────────┐
│ Another Card...                │
└─────────────────────────────────┘
                       ← 48px     ← Between groups
┌─────────────────────────────────┐
│ DIFFERENT SECTION               │

Padding vs. Margin

PropertyUse ForBehavior
PaddingSpace inside an elementIncreases the element's clickable/visible area
MarginSpace between elementsCreates separation from siblings
GapSpace between grid/flex childrenClean, no collapsing issues, preferred

Prefer gap over margin when using flexbox or grid. It's cleaner, more predictable, and doesn't have margin collapsing issues.

/* Prefer this */
.card-grid {
  display: grid;
  gap: 24px;   /* Clean, consistent, no collapsing */
}

/* Over this */
.card {
  margin-bottom: 24px;
  margin-right: 24px;
  /* Last items have unwanted margin, needs negative margin hacks */
}

Common Layout Mistakes

MistakeWhy It Looks BadFix
Content stretching to full viewport width on large screensLines become too long (80+ characters), content is hard to scanUse a max-width container (1200-1440px)
Equal spacing everywhereNo visual grouping, everything blurs togetherUse less space within groups, more between groups
Inconsistent padding in cardsSome cards have 12px, others 24px, looks unfinishedDefine a component padding token and use it consistently
No responsive spacingDesktop-sized margins crush mobile contentScale spacing down on mobile, up on desktop
Using pixel values directlyHard to maintain, inconsistent across the codebaseUse spacing tokens (CSS variables)
Fixed heights on containersContent overflows or creates unwanted scrollUse min-height or let content determine height
Vertical rhythm breaksLine heights and margins don't align to the gridUse the 8px grid for all vertical measurements

Quick Reference

Spacing Decision Tree

What are you spacing?

1. Text line to text line → line-height (1.5-1.6 for body)
2. Label to its input → 4-8px
3. Input to next input → 16-20px
4. Group to group → 24-32px
5. Section to section → 48-120px (responsive)
6. Inside a card → 16-24px padding
7. Between cards → 16-24px gap
8. Page side margins → 16px mobile, 24-48px desktop

Key Takeaways

  • Use the 8px grid. All spacing, sizing, and positioning should be multiples of 8 (with 4px for micro adjustments).
  • Define spacing tokens and use them everywhere. Never use arbitrary pixel values in code.
  • Space within groups < space between groups < space between sections. This creates visual hierarchy.
  • Use CSS Grid with auto-fill and minmax() for responsive card layouts without breakpoints.
  • Increase spacing proportionally at larger screen sizes. Don't just make content wider.
  • Prefer gap over margin for spacing between flex/grid children.
  • When in doubt, add more whitespace. Beginners consistently use too little.
  • Set a max-width container. No content should span 100% of a 2560px monitor.