Responsive design — UI that adapts to different screen sizes — is now the default. Single-screen-size designs are rare. The patterns have evolved: from breakpoint-heavy layouts to fluid, container-aware designs.
This page covers the modern principles.
Design for small screens first; enhance for larger screens.
/* Default: mobile */
.card {
padding: 16px;
}
/* Tablets and up */
@media (min-width: 768px) {
.card {
padding: 24px;
}
}
/* Desktop and up */
@media (min-width: 1024px) {
.card {
padding: 32px;
}
}
The mobile styles are the default. Larger screens add to them.
Why mobile-first:
These are conventions; actual breakpoints should match design needs, not arbitrary device sizes.
The "iPhone breakpoint" is wrong. Devices have many sizes; designing for specific phones leaves others poorly served.
Design for content. When the layout breaks down (text wraps oddly, columns squish), that's the breakpoint.
Move from fixed values to fluid:
/* Old: fixed */
.container { width: 1200px; }
/* Fluid: relative units, max bound */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 16px;
}
The container fills its parent up to 1200px, with margin to keep it centered.
Type that scales with viewport:
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
}
clamp(min, preferred, max):
Result: smooth typography across screen sizes without breakpoints.
Grid changes layout fundamentally:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 16px;
}
auto-fit + minmax(300px, 1fr):
Naturally responsive without breakpoints. Cards reflow as the container width changes.
Modern CSS feature. Style based on the container size, not the viewport:
.card-container {
container-type: inline-size;
}
.card {
/* Default */
}
@container (min-width: 400px) {
.card {
/* When the container is at least 400px wide */
}
}
Container queries enable truly modular components — a card behaves the same whether it's in a sidebar or main content, based on its container, not the page.
This is the long-awaited fix for component-level responsive design.
For one-dimensional layouts:
.row {
display: flex;
gap: 16px;
flex-wrap: wrap;
}
.row > * {
flex: 1 1 200px;
}
Items distribute; wrap when they can't fit; minimum 200px each.
For most simple "row of items" layouts, flexbox is the right tool. For 2D layouts, grid.
Responsive images use srcset:
<img src="image-800.jpg"
srcset="image-400.jpg 400w,
image-800.jpg 800w,
image-1600.jpg 1600w"
sizes="(min-width: 1024px) 50vw, 100vw"
alt="Description">
The browser picks the right image based on device pixel density and the rendered size.
For art direction (different crops at different sizes), use <picture>.
Mobile screens have less space. Decide what's essential:
The "show everything" approach produces unusable mobile experiences.
Mobile users often have slower networks and less powerful devices. Responsive doesn't help if mobile-loaded resources are huge.
Strategies:
srcset)For new responsive design: