--- name: designing-responsive-layouts description: Designs responsive CSS layouts — mobile-first breakpoints, flexbox vs grid decisions, container queries, fluid sizing with clamp(), and intrinsic auto-fit/minmax patterns. Use when the user asks to make a page or component responsive, build a layout or grid, fix overflow or squished content on mobile, choose between flexbox and grid, or add breakpoints or container queries. Do not use for page content composition and conversion structure (creating-landing-pages) or for color/spacing token systems (theming-design-tokens). --- # Designing Responsive Layouts ## When to use / when NOT to use - **Use for:** layout mechanics — grids, columns, wrapping, breakpoints, container queries, fluid sizing, overflow fixes. - **Do NOT use for:** what content goes where on a marketing page (→ creating-landing-pages); token scales and theming (→ theming-design-tokens); typography scales (→ choosing-typography). ## Core rules 1. **Mobile-first: base styles are the narrow layout; media queries only add width.** - ✅ `.cards { display: grid; } @media (min-width: 48rem) { .cards { grid-template-columns: 1fr 1fr; } }` - ❌ Desktop styles first, then `@media (max-width: …)` overrides undoing them 2. **Flexbox vs grid decision rule: one dimension → flexbox; two dimensions or explicit placement → grid.** Nav bars, button rows, media objects = flex. Card grids, page shells, dashboards = grid. 3. **Prefer intrinsic (no-breakpoint) patterns before adding media queries.** - ✅ `grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));` - ❌ Three hand-written breakpoints to go 1→2→3 columns 4. **Breakpoints in `rem`, chosen where the content breaks — not at device names.** Defaults when nothing else is known: 48rem (768px) and 80rem (1280px); always verify at 360px, 768px, 1280px. 5. **Components respond to their container, not the viewport.** - ✅ `.sidebar { container-type: inline-size; } @container (min-width: 24rem) { .card { flex-direction: row; } }` - ❌ A viewport media query that breaks the card when it's placed in a narrow sidebar 6. **Fluid values with `clamp()`, not stepped jumps:** `padding: clamp(1rem, 3vw, 2.5rem);` for space that scales; reserve breakpoints for structural change. 7. **Never fix heights on text containers; let content size the box.** - ✅ `min-height: 20rem;` (or nothing) - ❌ `height: 20rem; overflow: hidden;` — clips translated/user content and causes CLS 8. **Kill accidental horizontal scroll at the source:** media `max-width: 100%; height: auto;`, `min-width: 0` on flex/grid children that must shrink, `overflow-wrap: break-word` on long strings. ## Workflow 1. Identify the layout's dimensionality per rule 2 and pick flex or grid. 2. Build the narrow (360px) layout first with intrinsic patterns (rule 3). 3. Add `@container` or `@media (min-width)` steps only where the content visibly breaks. 4. Replace remaining fixed values with `clamp()`/`minmax()` where they should flex. 5. Validate: test at 360px, 768px, 1280px, and one in-between width; check no horizontal scrollbar, no clipped text, images scale, and layout shift stays visually stable (CLS ≤ 0.1 target). ## Edge cases & failure modes - **Flex children overflowing:** flex items default to `min-width: auto` — set `min-width: 0` on the shrinking child. - **`auto-fit` collapsing with one item stretched full width:** use `auto-fill` when empty tracks should be preserved. - **Container queries need a named/typed container:** without `container-type: inline-size` on an ancestor, `@container` silently never matches. - **`100vw` causes a scrollbar-width overflow on Windows:** use `100%` or `100dvw`. - **Legacy browser support required:** container queries and `dvh/dvw` need a media-query fallback — state the assumption before using them. ## References Copy-paste layout recipes (shells, card grids, sidebars, holy grail, media objects): see [references/patterns.md](references/patterns.md)