Responsive design in 2026 is dramatically better than the media-query-heavy past. Container queries, CSS Grid, subgrid, and modern units like clamp() and dvh have changed the game. Here's how to build responsive layouts with modern CSS.
The Modern Responsive Toolkit
| Feature | What It Does | Replaces |
|---|---|---|
| Container Queries | Style based on PARENT container size, not viewport | Media queries for component-level responsive |
| CSS Grid + subgrid | 2D layout with content-sized tracks | Flexbox hacks for complex layouts |
| clamp() | Fluid values: min, preferred, max in one line | Multiple media queries for font sizes |
| dvh / svh / lvh | Dynamic viewport height (accounts for mobile browser bars) | 100vh (broken on mobile Safari) |
| has() selector | Style parent based on children | JavaScript to toggle parent classes |
| color-mix() | Mix colors in CSS (no preprocessor needed) | Sass/SCSS color functions |
| @layer | Control CSS specificity order | Specificity wars and !important |
Container Queries โ The Game Changer
Media queries respond to the viewport. Container queries respond to the parent element. This means a component adapts to the space it's given โ not the browser window. Write once, drop into any layout.
/* Define a container */
.card-container {
container-type: inline-size;
container-name: card;
}
/* Style based on container width, NOT viewport */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}
Fluid Typography with clamp()
/* Instead of 5 media query breakpoints: */
h1 {
font-size: clamp(2rem, 5vw, 4rem);
/* min: 2rem, preferred: 5vw, max: 4rem */
/* Smoothly scales between viewport widths โ no breakpoints */
}
p {
font-size: clamp(1rem, 0.5vw + 0.875rem, 1.25rem);
}
/* Fluid spacing too */
section {
padding: clamp(1rem, 5vw, 4rem) clamp(1rem, 5vw, 6rem);
}
Modern Grid Layout
/* Auto-responsive grid โ no media queries needed */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: 1rem;
}
/* min(300px, 100%) โ prevents overflow on mobile.
auto-fit โ adds/removes columns as space allows.
This one line replaces 3 media queries. */
Dynamic Viewport Height (Fix Mobile Safari)
/* Old way โ broken on mobile (Safari toolbar overlaps) */
.hero {
height: 100vh; /* โ Content hidden behind Safari toolbar */
}
/* New way โ accounts for dynamic toolbar */
.hero {
height: 100dvh; /* โ
Works on all mobile browsers */
/* dvh = dynamic viewport height.
svh = smallest (toolbar visible).
lvh = largest (toolbar hidden). */
}
The :has() Selector โ Parent Styling
/* Style a card differently when it contains an image */
.card:has(img) {
grid-column: span 2;
}
/* Style form group when input is invalid */
.form-group:has(input:invalid) {
border-left: 3px solid red;
}
/* Style a section when it's empty */
section:has(:not(*)) {
display: none;
}
Responsive Layout Patterns
| Pattern | CSS | Use Case |
|---|---|---|
| Sidebar + Content | grid-template-columns: minmax(250px, 25%) 1fr | Admin panels, documentation |
| Card Grid | repeat(auto-fit, minmax(min(300px, 100%), 1fr)) | Blog lists, product grids |
| Holy Grail Layout | Grid with header, 2 sidebars, content, footer | Full-page layouts |
| Stack | flex-direction: column; gap: clamp(1rem, 3vw, 2rem) | Articles, landing pages |
Bottom line: Container queries + clamp() + auto-fit grid eliminate 80% of media queries. Modern CSS has absorbed what Bootstrap and Tailwind solved โ you can build fully responsive layouts with zero framework CSS. See also: CSS Framework Comparison and Design Tools Guide.