CSS Grid in 2026: A Practical Guide With Real Layout Examples

CSS Grid handles two-dimensional layouts where rows and columns must line up, like page shells, card galleries, and dashboards. Flexbox still wins for one-direction stacks and rows. I use Grid for the page skeleton and flexbox inside components. Support is universal, so there is no reason to avoid it.
Part of the complete web design guide.
On this page
- Grid vs flexbox: pick the right tool
- The core concepts, fast
- A basic two-column shell
- Responsive without media queries
- Named areas make layouts readable
- Common mistakes I still see
- Subgrid is finally safe to use
- Where this shows up in real projects
- FAQ
- Is CSS Grid supported everywhere in 2026?
- Should I stop using flexbox?
- Do I need a framework to use Grid?
Most sites I look at still use flexbox for everything, then fight it when a real two-dimensional layout shows up. CSS Grid solves that problem, and browser support has been universal for years now, so there’s no reason to hold back. Here’s how I actually use it, with code you can drop into a project today.

Grid vs flexbox: pick the right tool
The rule I give people is simple. Flexbox is for laying things out in one direction: a row of buttons, a stack of form fields, a nav bar. Grid is for when you need rows and columns to line up at the same time. Card galleries, page shells, dashboard panels, pricing tables. If you find yourself nesting three flex containers to get a layout, that’s your signal to switch.
You can absolutely mix them. I use Grid for the page skeleton and flexbox inside individual components all the time. They’re not competing.

The core concepts, fast
Grid has a small vocabulary. Once these click, you’re 90% of the way there.
- Grid container: the parent element with
display: grid. - Grid items: its direct children. Nothing deeper.
- Tracks: the rows and columns you define.
- Gaps: the space between tracks, set with
gap, not margins. - Lines: the numbered edges between tracks. You place items by line number.
A basic two-column shell
.layout {
display: grid;
grid-template-columns: 240px 1fr;
gap: 2rem;
}
/* Everything after the first column fills the rest */
.layout > .sidebar { grid-column: 1; }
.layout > .main { grid-column: 2; }
The 1fr unit means “one share of the leftover space.” Two 1fr columns split evenly. A fixed 240px plus 1fr gives you a fixed sidebar and a fluid main area.
Responsive without media queries
This is the part that saves me the most time. Instead of writing breakpoints for a card grid, you let the browser decide how many columns fit.
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 1.5rem;
}
Read it out loud: repeat a column that’s at least 260px wide but can grow to fill the space, as many times as will fit. On a phone you get one column. On a laptop you get three or four. No media queries, no JavaScript. I’ve shipped this exact pattern on client sites for years and it just works.
One gotcha: auto-fit collapses empty tracks, auto-fill keeps them. If you have a single card and want it to stretch full width, use auto-fit.
Named areas make layouts readable
For anything with a real page structure, grid-template-areas is worth the extra typing because the CSS reads like a diagram.
.page {
display: grid;
grid-template-columns: 1fr minmax(auto, 70ch) 1fr;
grid-template-areas:
"header header header"
". main ."
"footer footer footer";
gap: 1rem;
}
.page > header { grid-area: header; }
.page > main { grid-area: main; }
.page > footer { grid-area: footer; }
That middle row is a classic readable-width trick: a centered content column with gutters on each side, capped at 70 characters. The dots mean “leave this cell empty.”
Common mistakes I still see
- Using margins for spacing. Use
gapon the container. It handles the edges correctly and doesn’t double up. - Fighting implicit rows. Items you don’t place get auto-placed. If things land somewhere weird, add
grid-auto-flow: row dense;or place them explicitly. - Overusing grid for one-dimensional stuff. A single row of items is a flexbox job. Don’t make it harder than it is.
- Forgetting the min-width.
minmax(0, 1fr)prevents long words and code blocks from blowing out a column. I hit this constantly with preformatted text.
Subgrid is finally safe to use
After years of waiting, grid-template-columns: subgrid works across all current browsers in 2026. It lets a child align to its parent’s tracks instead of defining its own, which fixes the old “cards have uneven heights and nothing lines up” headache.
.card-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* title, body, footer line up across all cards */
}
If you’ve ever hacked equal-height cards with fixed pixel values, this replaces all of it.
Where this shows up in real projects
Layout choices matter more on content-heavy sites than on simple landing pages. I do a fair amount of Long Island web design work for local businesses, and the pattern is always the same: they need a site that looks right on a phone, a tablet, and a desktop monitor without a pile of custom CSS for each. Grid’s intrinsic sizing does most of that work for free.
If you’re maintaining an older site built on floats or table layouts, you don’t have to rewrite everything at once. Pick one section, convert it to Grid, and see how much CSS you delete. That’s usually the moment it clicks.
FAQ
Is CSS Grid supported everywhere in 2026?
Yes. Every current browser supports the full Grid spec including subgrid. You don’t need fallbacks for modern browsers, though you may still need them if you support very old enterprise environments.
Should I stop using flexbox?
No. Use flexbox for one-dimensional layouts and Grid for two-dimensional ones. Most real pages use both.
Do I need a framework to use Grid?
No. Grid is native CSS. Frameworks like Tailwind wrap it in utility classes, but plain CSS works fine and is often easier to read for layout code.


