VS Vikesh Singh

Courses CSS Lesson 9

CSS · LESSON 9 OF 18

CSS Grid: When Flexbox Isn't Enough

· 4 min read

Flexbox, from the last lesson, is excellent at arranging items in a single row or a single column.

Flexbox, from the last lesson, is excellent at arranging items in a single row or a single column. But what happens when you need a true two-dimensional layout, rows and columns that line up together, like a photo gallery, a dashboard, or a classic webpage layout with a header, sidebar, main content, and footer all aligned on a shared grid? Flexbox can approximate this with wrapping, but it was never truly designed for it. CSS Grid was built specifically for two-dimensional layout, and this lesson introduces it properly.

Creating A Grid Container

You turn an element into a grid container the same way you turn one into a flex container, just with a different value.

<div class="gallery">
  <div class="photo">1</div>
  <div class="photo">2</div>
  <div class="photo">3</div>
  <div class="photo">4</div>
  <div class="photo">5</div>
  <div class="photo">6</div>
</div>
.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
}

grid-template-columns: 1fr 1fr 1fr creates exactly three equal-width columns, and every child automatically flows into them, wrapping onto new rows once a row fills up, without you writing any wrapping logic at all. The fr unit means "fraction of the remaining space," which is unique to grid; 1fr 1fr 1fr means split the space into three equal parts, while 2fr 1fr 1fr would make the first column twice as wide as the other two.

Responsive Columns With Auto Fit

A particularly powerful pattern for responsive galleries uses repeat() combined with minmax(), letting the browser decide how many columns fit without you writing a single media query.

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 16px;
}

This single line says: fit as many columns as possible, each at least 150px wide, and stretch them to fill any remaining space evenly. On a wide monitor you might get six columns, on a phone you might get two, and the browser recalculates automatically as the window resizes. This is one of the most genuinely magical one-liners in modern CSS, and it solves a problem that used to require many lines of media queries.

Defining Rows And Layout

Grid also lets you define rows explicitly, not just columns.

.layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

Here, the first column is a fixed 220px sidebar, and the second takes up the rest of the space (1fr). The rows are set to auto (size to content, for a header), 1fr (take remaining space, for the main content), and auto again (size to content, for a footer). This single declaration sets up the skeleton of an entire classic page layout.

Named Grid Template Areas

You can place specific items into specific named areas using grid-template-areas, which is one of grid's most readable features, because the CSS itself visually resembles the layout.

<div class="layout">
  <header class="site-header">Header</header>
  <nav class="site-nav">Nav</nav>
  <main class="site-main">Main content</main>
  <footer class="site-footer">Footer</footer>
</div>
.layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-areas:
    "header header"
    "nav    main"
    "footer footer";
  gap: 12px;
}

.site-header { grid-area: header; }
.site-nav    { grid-area: nav; }
.site-main   { grid-area: main; }
.site-footer { grid-area: footer; }

Reading the grid-template-areas block is almost like looking at a little map of the page: header spans the full width on top, nav sits in the left column next to main, and footer spans the full width at the bottom. This readability is a major reason professional developers reach for grid when building whole-page layouts, rather than nesting several flexbox containers inside each other.

Grid Versus Flexbox

A common beginner mistake is trying to use grid for something that's really just a single row of items, like a simple button group, where flexbox would be simpler and more appropriate. A helpful rule of thumb: if you're only thinking in one direction (just a row, or just a column), reach for flexbox; if you're thinking in both directions at once (rows and columns that need to align together), reach for grid. Many real pages actually use both together, grid for the overall page skeleton, flexbox for smaller components inside each grid area, like a row of buttons inside the header.

Another common mistake is forgetting gap, and instead trying to add spacing with margins on individual grid items, which can create uneven or doubled-up spacing at the edges. Grid's own gap property handles spacing between cells cleanly without affecting the outer edges of the grid itself.

Practical tip: when designing any new page layout, sketch it as a rough grid of boxes first (even on paper), identify the main regions, and then translate that directly into grid-template-areas, naming each region something sensible like header, sidebar, main, footer.

Spanning Columns And Rows

Grid items can also span multiple columns or rows deliberately, using grid-column and grid-row, which is handy for a featured item in a gallery that deserves extra visual weight.

.photo:first-child {
  grid-column: span 2;
  grid-row: span 2;
}

Here, the very first photo occupies a two-by-two block instead of a single cell, letting it stand out as a highlighted item while the rest of the gallery continues to flow normally around it, a common pattern in magazine-style layouts and image grids.

Try it yourself: build a simple page skeleton with a header, a left sidebar, main content, and a footer using grid-template-areas, then build a separate responsive photo gallery using repeat(auto-fit, minmax(150px, 1fr)) and resize your browser window to watch the column count change automatically.