Patterns — Responsive Layouts
Contents
- Auto-responsive card grid (no breakpoints)
- Page shell (header/content/footer)
- Sidebar + content (collapses on narrow)
- Container-query card
- Media object
- Fluid space and size
- Overflow-proofing checklist
- Gotchas
Auto-responsive card grid (no breakpoints)
css
.cards {
display: grid;
/* min(16rem, 100%) prevents overflow when the container is narrower than 16rem */
grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
gap: 1rem;
}Page shell (header/content/footer, footer pinned)
css
body {
min-height: 100dvh; /* dvh avoids mobile URL-bar jump; fallback: 100vh */
display: grid;
grid-template-rows: auto 1fr auto;
}Sidebar + content (collapses on narrow)
css
/* Flexbox version — wraps naturally, no media query */
.with-sidebar {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.with-sidebar > .sidebar { flex: 1 1 15rem; } /* basis = collapse point */
.with-sidebar > .content { flex: 999 1 60%; min-width: 0; }css
/* Grid version — explicit breakpoint */
.shell { display: grid; gap: 1.5rem; }
@media (min-width: 48rem) {
.shell { grid-template-columns: 15rem minmax(0, 1fr); }
}Container-query card
css
.card-slot { container-type: inline-size; }
.card { display: flex; flex-direction: column; gap: 0.75rem; }
@container (min-width: 24rem) {
.card { flex-direction: row; align-items: center; }
.card img { max-width: 40%; }
}Media object (avatar + text)
css
.media { display: flex; gap: 0.75rem; align-items: flex-start; }
.media > img { flex-shrink: 0; width: 3rem; height: 3rem; border-radius: 50%; }
.media > .body { min-width: 0; } /* lets long words/URLs shrink instead of overflow */Fluid space and size
css
:root {
/* 1rem at 320px viewport → 2.5rem at 1280px, linear between */
--space-section: clamp(1rem, 0.5rem + 2.5vw, 2.5rem);
--content-max: 72rem;
}
.section { padding-block: var(--space-section); }
.container {
width: min(100% - 2rem, var(--content-max));
margin-inline: auto;
}Overflow-proofing checklist
css
img, video, canvas, svg { max-width: 100%; height: auto; }
.flex-child, .grid-child { min-width: 0; } /* on anything that must shrink */
.prose { overflow-wrap: break-word; } /* long URLs, tokens */
table { display: block; overflow-x: auto; } /* wide data tables scroll alone */Test sequence: 360px → 768px → 1280px → one odd width (e.g. 913px). Look for: horizontal scrollbar, clipped text, stretched images, wrap orphans.
Gotchas
minmax(16rem, 1fr)overflows below 16rem — always wrap the minimum inmin(16rem, 100%).auto-fitvsauto-fill: auto-fit collapses empty tracks (items stretch); auto-fill keeps them (items stay small). One word, opposite layouts.- Flex
min-width: autodefault means text children refuse to shrink — the single most common "why is this overflowing" cause. - Percentage heights need a sized ancestor; prefer grid rows (
1fr) ormin-heightchains. gapon flexbox is fine everywhere modern; if supporting old Safari (<14.1), fall back to margins.- Nested containers:
@containerresolves against the nearest ancestor withcontainer-type— name containers (container-name: card-slot) when nesting. 100dvhvs100vh: dvh tracks the dynamic mobile toolbar; vh can leave a gap or cause scroll. Provide100vhfirst as fallback on the previous line.