Responsive CSS Layouts in 2026: Grid, Container Queries, and What Actually Works

Use CSS Grid for page structure and Flexbox for components, then container queries for anything reusable. Card grids need no media queries: repeat(auto-fit, minmax(min(280px, 100%), 1fr)) handles almost every width. That min() is what keeps small phones from breaking.
Part of the complete web design guide.
On this page
- Start with Grid for page structure, Flexbox for components
- Container queries changed component design
- Fluid type without the guesswork
- Logical properties, especially if you build anything multilingual
- Use dvh, not vh, for full-height sections
- When you don’t need a framework
- Test on a real phone, not just a resized browser window
- FAQ
- Do I still need media queries at all?
- Is container queries support safe to use in 2026?
- Should I use rem or px for breakpoints?
Responsive CSS got a lot better while most people weren’t looking. The old tricks (float clears, a dozen media queries, JavaScript measuring element widths) are mostly obsolete now. If you’re still laying out sites the 2018 way, you’re writing more code than you need and it breaks in places you didn’t test.
Here’s what I actually reach for in 2026, in the order I reach for it.
Start with Grid for page structure, Flexbox for components
This isn’t new advice, but people still get it backwards. Grid is for two-dimensional layout: the overall page, card grids, anything with rows and columns that need to line up. Flexbox is for one-dimensional flow: a nav bar, a button with an icon, a row of tags.
The single most useful line of CSS for a card grid is still this:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
gap: 1.5rem;
}
That min(280px, 100%) inside minmax() is the part people miss. Without it, a 280px minimum blows out the layout on a 320px phone. With it, the column just shrinks. No media query, no breakpoints, and it responds to the container, not the viewport.
Container queries changed component design
Container queries are baseline across every major browser now, and they solve a problem media queries never could. A card doesn’t care how wide the viewport is. It cares how wide its own slot is. Same card in a sidebar and in a full-width hero should look different, and now it can without duplicating markup.
.card-wrap {
container-type: inline-size;
container-name: card;
}
.card {
display: flex;
flex-direction: column;
gap: 1rem;
}
@container card (min-width: 400px) {
.card {
flex-direction: row;
align-items: center;
}
}
Once you internalize this, you stop writing “mobile-first” as a global philosophy and start writing “component-first.” The component decides its own layout based on the room it’s given. That’s a real shift, and it’s the biggest one in CSS since Grid landed.
Fluid type without the guesswork
You don’t need a media query to resize a heading between two breakpoints. Use clamp() with a viewport unit in the middle:
h1 {
font-size: clamp(2rem, 1.5rem + 2.5vw, 3.5rem);
line-height: 1.1;
}
The middle value is the fluid part. The rem in there matters: it keeps the text scaling with the user’s font-size preference, which a pure vw value does not. That’s an accessibility issue, not a nicety. If someone sets their browser default to 24px because they can’t read 16px, a vw-only heading ignores them.
Set the minimum and maximum by eye, not by formula. The formula is a starting point. Your eyes are the actual judge.
Logical properties, especially if you build anything multilingual
Physical properties (margin-left, padding-right, left) assume the text flows left to right. Logical properties don’t:
.callout {
margin-inline-start: 1rem;
padding-block: 1.5rem;
border-inline-start: 3px solid currentColor;
}
Same result in English. Flip the page to Arabic or Hebrew and the layout mirrors itself with zero extra CSS. Even for an English-only site, I use logical properties by default now. It’s the same number of keystrokes and it future-proofs the thing.
Use dvh, not vh, for full-height sections
The mobile browser address bar has been lying to 100vh for years. On a phone, 100vh is taller than the visible area, so your “full screen” hero gets cut off at the bottom. The dynamic viewport units fix this:
.hero {
min-height: 100dvh;
}
dvh resizes as the browser chrome shows and hides. svh is the smallest possible viewport, lvh the largest. For a hero you usually want dvh or svh. This one line has saved me more client complaints than anything else on this list.
When you don’t need a framework
I’ve shipped plenty of Tailwind and Bootstrap sites. They’re fine tools. But if your layout is a header, a few sections, and a footer, you don’t need a utility framework to get there. Grid, Flexbox, container queries, and clamp() cover most of what a small business site actually needs, with a fraction of the markup and none of the build step.
The honest test: if you’re fighting a framework’s grid system more than you’re using it, drop the framework. You’ll ship faster. I’ve had that conversation with plenty of business owners around here. A lot of local sites I look at are carrying 200KB of CSS framework to lay out five sections. For anyone doing Long Island web design, that’s usually the wrong trade.
Test on a real phone, not just a resized browser window
DevTools device emulation is a good approximation and a bad substitute. It doesn’t reproduce the dynamic viewport behavior, real touch targets, or the way Safari handles position: fixed when the keyboard opens. Grab the cheapest Android phone you can find and the oldest iPhone still getting updates. Ten minutes with those two devices catches things an hour in DevTools won’t.
And keep an eye on your Lighthouse or PageSpeed score after you add container queries. They’re cheap, but if you nest them five levels deep you’re asking the browser to do more work per frame than it needs to.
FAQ
Do I still need media queries at all?
Yes, but far fewer. Use them for genuinely different layouts (a sidebar that only appears on wide screens), not for every font-size tweak. Container queries and clamp() handle most of what media queries used to do.
Is container queries support safe to use in 2026?
Yes. It’s baseline across Chrome, Safari, Firefox, and Edge. If you’re supporting very old browsers, feature-detect with @supports (container-type: inline-size) and provide a fallback, but for most sites that’s unnecessary now.
Should I use rem or px for breakpoints?
Use em in media query conditions. It respects the user’s font-size setting, so someone who’s bumped their default text size gets the wider layout sooner. Inside your actual layout rules, rem for spacing and type, px is fine for borders and hairlines.


