Grid vs. Flexbox: Choosing the Right Tool
Flexbox is one-dimensional, it lays items out in a single row or a single column. CSS Grid is two-dimensional, it controls rows and columns at the same time. If you are picturing a full page layout, a header across the top, a sidebar down the left, a main content area, and a footer, that is a grid problem. If you are picturing a single row of navbar links or a stack of buttons, that is a Flexbox problem. Most real interfaces use both, Grid for the page skeleton, Flexbox for the components inside it.
Creating a Grid Container
Just like Flexbox, Grid starts with one property on a parent element:
.container {
display: grid;
}
On its own that does nothing visible yet, because you have not told the browser how many columns or rows
to create. That is what grid-template-columns and
grid-template-rows are for.
Defining Columns With grid-template-columns
.container {
display: grid;
grid-template-columns: 200px 1fr 1fr;
gap: 1.5rem;
}
This creates exactly three columns: a fixed 200-pixel column, then two flexible columns that split the
remaining space equally. The fr unit stands for "fraction" and is unique
to Grid, it means "one share of whatever space is left over," which makes it perfect for responsive
columns that never need a calculated pixel value.
Reading fr values: grid-template-columns: 1fr 2fr;
creates two columns where the second is always exactly twice as wide as the first, no matter the
container size.
The repeat() Shortcut
Writing 1fr 1fr 1fr 1fr for a four-column grid gets tedious. The
repeat() function does it for you:
.gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}
This is exactly equivalent to writing 1fr 1fr 1fr 1fr, four equal columns,
but scales far better when you need twelve columns or need to change the number later.
Truly Responsive Grids Without Media Queries
This is where Grid becomes genuinely powerful. Combine repeat() with
auto-fit and minmax() and you get a grid
that reflows itself automatically as the viewport resizes, no breakpoints required.
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1.5rem;
}
Translated into plain language: "Fit as many columns as you can, each at least 240px wide, and stretch them to fill any leftover space." On a wide monitor this might render five columns, on a tablet three, on a phone one, all from a single line of CSS. This exact pattern is used for the tutorial cards on this page's blog overview.
Rows, and the Difference Between fr and auto
Rows work the same way, using grid-template-rows. A common full-page
layout fixes the header and footer height while letting the main content stretch to fill whatever space
is left:
body {
display: grid;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
auto means "just tall enough for the content inside," used for the header
and footer. 1fr means "take all the remaining vertical space," used for
the main content area. Together they guarantee the footer sits at the bottom of the viewport even on pages
with very little content, a problem that used to require JavaScript to solve properly.
Placing Items With grid-column and grid-row
Sometimes you want a specific item to span multiple columns, a featured card that is twice as wide as the others, for example.
<div class="grid">
<div class="item featured">Featured</div>
<div class="item">Regular</div>
<div class="item">Regular</div>
</div>
<style>
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}
.featured {
grid-column: span 2; /* spans two of the four columns */
}
</style>
grid-column: span 2 tells that single item to occupy two column tracks
instead of one, while every other item without that rule automatically claims a single column. This kind
of asymmetric, magazine-style layout is genuinely difficult with Flexbox and trivial with Grid.
Named Grid Areas for Full-Page Layouts
For a whole-page layout, grid-template-areas lets you literally draw the
layout in your CSS using names.
.page {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
Each row of quoted text in grid-template-areas is literally a visual row
of your page, and each word is which named area occupies that cell. The sidebar spans all three rows
because "sidebar" appears in every line. This is, in my opinion, the most
readable way to build a page layout in all of CSS, you can look at the property and see the shape of the
page instantly.
Grid and Flexbox Working Together
In practice, you will nest them. A page uses Grid for its overall skeleton, and inside individual grid cells you use Flexbox to align smaller groups of items, like the icon and text inside a single card. Neither tool replaces the other, they solve different dimensions of the same problem.
Next Steps
With HTML structure, Flexbox, and Grid under your belt, you have the core layout skills to build real pages. The next skill to add is interactivity. Read our guide on JavaScript DOM manipulation to make your layouts respond to clicks and input.
Ready to go beyond one tutorial?
This lesson is one piece of the full CodeVent Digital frontend curriculum. Start free and build real projects step by step.
Start Learning Free