Responsive Design
Build layouts that adapt to any screen size with modern CSS
Responsive Design Fundamentals
Responsive design means one HTML source adapts to every viewport. Three pillars: fluid grids, flexible images, media queries.
Media Queries
Media queries test device characteristics. Three common uses:
/* Min-width (mobile-first): apply above threshold */
@media (min-width: 768px) {
.sidebar {
display: block;
}
}
/* Max-width (desktop-first): apply below threshold */
@media (max-width: 767px) {
.nav-menu {
display: none;
}
}
/* User preference queries */
@media (prefers-reduced-motion: reduce) {
.animated {
animation: none;
}
}
@media (prefers-color-scheme: dark) {
body {
background: #111;
color: #eee;
}
}
Start with base styles for small screens, then add media queries for larger breakpoints. Less code, fewer overrides, naturally accessible baseline.
Container Queries
Query the parent container's size, not the viewport.
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
flex-direction: row;
}
}
@container (min-width: 600px) {
.card {
grid-template-columns: 1fr 2fr;
}
}
Fluid Sizing with clamp()
clamp(MIN, PREFERRED, MAX) — fluid values that stay within bounds.
h1 {
font-size: clamp(1.5rem, 4vw + 1rem, 3rem);
}
.card {
padding: clamp(1rem, 3vw, 2.5rem);
}
.container {
width: min(90vw, 1200px);
} /* never exceeds 1200px */
Modern Viewport Units
100vh on mobile includes the browser chrome. New units fix this:
| Unit | Meaning |
|---|---|
dvh | Dynamic viewport height (changes as chrome shows/hides) |
svh | Smallest viewport height (safe baseline) |
lvh | Largest viewport height (full screen) |
dvw | Dynamic viewport width |
.hero {
height: 100dvh;
} /* adapts to mobile toolbars */
.fixed-footer {
height: 10svh;
} /* safe minimum */
Common Responsive Pattern
Stacked layout on mobile, side-by-side on desktop:
.layout {
display: grid;
grid-template-columns: 1fr; /* mobile: single column */
gap: 1rem;
}
@media (min-width: 768px) {
.layout {
grid-template-columns: 250px 1fr; /* desktop: sidebar + main */
}
}
@media (min-width: 1024px) {
.layout {
grid-template-columns: 250px 1fr 300px; /* wide: sidebar + main + aside */
}
}
1<div class="card-grid">2<div class="card">Item 1</div>3<div class="card">Item 2</div>4<div class="card">Item 3</div>5<div class="card">Item 4</div>6<div class="card">Item 5</div>7<div class="card">Item 6</div>8</div>A fluid card grid adapting from 1 column on mobile to 3 columns on desktop using CSS Grid `auto-fit` and `minmax()`. No media queries needed.