Responsive layout

Have Agents implement layout from project breakpoints, container width, and a mobile-first strategy, covering landscape, foldables, and comfortable reading width on large screens.

The SKILL should list standard breakpoints (px or rem), max content width (measure), sidebar collapse rules, and whether @container wraps card grids; acceptance must cover typical device widths and minimum height, not desktop-only viewports.

Align with the CSS architecture skill: layout class naming, utilities vs component responsibility; if print or PDF export exists, add media-type rules beyond breakpoints.

  • Acceptance checklist: key pages at typical widths + min height via screenshots or a Story viewport matrix.
  • For landscape / fold inner–outer screens when relevant, document whether breakpoints or container strategy tie to “unfolded width.”

Breakpoint System and Mobile-First Media Queries

/* Breakpoint system: CSS variables (kept in sync with Design Tokens) */
:root {
  --bp-sm: 36rem;   /* 576px  - phone landscape */
  --bp-md: 48rem;   /* 768px  - tablet */
  --bp-lg: 64rem;   /* 1024px - small desktop */
  --bp-xl: 80rem;   /* 1280px - large desktop */
  --content-max-width: 72rem;  /* max content width */
}

/* Mobile-first: base styles target the narrowest viewport; min-width adds progressively */
.card-grid {
  display: grid;
  grid-template-columns: 1fr;         /* base: single column */
  gap: var(--space-4);
}

@media (min-width: 48rem) {           /* md: two columns */
  .card-grid { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 64rem) {           /* lg: three columns */
  .card-grid { grid-template-columns: repeat(3, 1fr); }
}

/* Desktop-first (for comparison — not recommended for new projects) */
/* .card-grid { grid-template-columns: repeat(3, 1fr); } */
/* @media (max-width: 64rem) { grid-template-columns: 1fr 1fr; } */

/* clamp() fluid typography: min / preferred / max */
h1 { font-size: clamp(1.5rem, 4vw + 0.5rem, 3rem); }  /* 24px → 48px fluid */
p  { font-size: clamp(1rem, 1vw + 0.75rem, 1.25rem); }
.container { padding-inline: clamp(1rem, 5vw, 3rem); } /* responsive padding */

The table below is a sample convention (replace with your design system):

Band Viewport (sample) Typical use
base < 36rem Single column, full-width actions, collapsed nav
md ≥ 48rem Two-column summaries, sidebar can appear
lg ≥ 64rem Three-column grid, fixed sidebar width
xl ≥ 80rem Max content width + margins, large-screen whitespace

Container Queries and Grid+Flexbox Combination Layout

/* Container Query: component width determined by parent, not viewport */
.sidebar-widget {
  container-type: inline-size;
  container-name: widget;  /* named container: enables targeted queries */
}

/* @container: same component adapts in narrow sidebar vs wide main area */
.widget-grid {
  display: grid;
  grid-template-columns: 1fr;  /* default: single column */
}

@container widget (min-width: 28rem) {
  .widget-grid { grid-template-columns: 1fr 1fr; }
}

@container widget (min-width: 44rem) {
  .widget-grid { grid-template-columns: repeat(3, 1fr); }
}

/* @supports fallback for browsers that don't support container queries */
@supports not (container-type: inline-size) {
  .widget-grid { grid-template-columns: 1fr 1fr; }
}

/* Grid + Flexbox combination layout */
.page-layout {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  grid-template-columns: 240px 1fr;  /* fixed sidebar + flexible main area */
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

/* Use Flexbox inside main area for content flow */
.page-main {
  grid-area: main;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: var(--space-6);
}

/* Mobile: collapse sidebar */
@media (max-width: 48rem) {
  .page-layout {
    grid-template-areas: "header" "main" "footer";
    grid-template-columns: 1fr;
  }
  .page-sidebar { display: none; }  /* or use transform for slide-in */
}

Document container names (container-name), query thresholds, and fallbacks: single-column when container queries are unsupported, or approximate layout via @supports.

Boundary for Agents: page-level nav, full-screen overlays, and root font scaling still favor viewport media queries; internal “column count / density” should prefer container queries so modules are not hard-wired to global breakpoints only.

Layout decision flow

  [ Design / grid contract ]
        │
        ▼
  ┌─────────────┐     Root typography: clamp / rem, max-width (measure)
  │ Fluid & measure │── safe area, viewport-fit, landscape min height
  └─────────────┘
        │
        ▼
  ┌─────────────┐     Nav / full-page split / theme: @media (min-width …)
  │ Viewport BP  │── mobile-first order, tokens aligned with design
  └─────────────┘
        │
        ▼
  ┌─────────────┐     Cards / toolbars / modules in rails: container + @container
  │ Container Q  │── names, thresholds, no-support single-column fallback
  └─────────────┘
        │
        ▼
  ┌─────────────┐     srcset/sizes, table scroll or stack, touch targets ≥ 44×44 CSS px
  │ Media & Ix   │── foldables, keyboard focus, prefers-reduced-motion
  └─────────────┘
        │
        ▼
  [ Viewport matrix screenshots / Story multi-viewport + key container widths ]

Media, tables, and touch

Specify srcset/sizes or CSS object-fit strategies so small screens do not download oversized assets; document horizontal scroll for wide tables (overflow-x, sticky header strategy) or stacked layouts on narrow viewports.

Call out minimum touch target size, safe areas (notch), and viewport-fit when relevant; review animation downgrades with prefers-reduced-motion.

In-page demo: viewport band and container width

The script below runs only on this page: the readout shows current viewport width and a sample breakpoint band; drag the slider to change the query container width and watch columns switch at @container (min-width: 22rem).

Block A Single column when the container is narrow.
Block B Sits beside A when width ≥ 22rem.

SKILL outline

---
name: responsive-layout
description: Implement consistent cross-device layout from breakpoints and container strategy
---
# Breakpoint system
1. Define breakpoints as CSS variables: --bp-sm/md/lg/xl, kept in sync with Design Tokens
2. Mobile-first: base styles target the narrowest viewport; enhance with min-width progressively (do not override with max-width)
3. Max content width (--content-max-width) defined centrally; avoid scattering it across individual components

# Fluid typography and spacing
4. clamp() fluid font sizes: clamp(min, preferred-vw-calc, max) covering headings, body, and padding
5. Fluid spacing: use clamp() or space tokens for padding/gap; avoid hard cuts at breakpoints

# Layout choices
6. Page-level columns / nav / overlays: @media min-width viewport breakpoints
7. Component-internal column count / density (cards / tables / toolbars): container-type + @container
8. Container naming (container-name): use business-semantic names for targeted @container queries
9. Grid: two-dimensional layout (page-layout); Flexbox: one-dimensional content flow (toolbars / lists)

# Compatibility and acceptance
10. @container without browser support: use @supports to provide single-column / two-column fallback
11. Touch targets: minimum 44×44 CSS px; the touch area may be larger than the visual size via padding
12. Landscape / foldables: document minimum-height strategy and whether unfolded width affects breakpoints
13. srcset/sizes: provide appropriate resolution per breakpoint; prevent small screens from loading large images
14. Reduced motion: use prefers-reduced-motion to downgrade animations
15. Acceptance matrix: screenshots at 375/768/1280/1920 width × portrait/landscape

Back to skills More skills