CSS Grid is the missing puzzle piece to your Flexbox knowledge. While Flexbox handles one-dimensional layouts, Grid gives you full control over rows AND columns simultaneously. This article covers everything from basics to subgrid, with practical examples you can use right away.

You know Flexbox? Great. Time to meet the big sibling. CSS Grid isn't better than Flexbox, it's the counterpart. Together, they're unstoppable.

Let's start from the top.

🤔 Grid vs. Flexbox: 1D vs. 2D

Flexbox works in one direction. Either horizontal or vertical. That's perfect for navbars, toolbars, or a row of buttons.

Grid works in two directions at once. Rows and columns. That makes it ideal for full page layouts, dashboards, and anything where you need to place elements on a grid.

In short:

  • Flexbox = arrange elements in a line (1D)
  • Grid = arrange elements in a grid (2D)
Why CSS Flexbox can solve your layout problems 🧑‍💻
If you're not familiar with Flexbox yet – here's the perfect starting point.

🏗️ Grid Basics: Your First Grid

Creating a grid is surprisingly simple. All you need is a container with display: grid and a definition for columns and/or rows.

.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  gap: 1rem;
}

That's it. Three columns, three rows. The middle column takes up all remaining space. Easy, right?


  Header
  Sidebar
  Content
  Aside
  Footer

📐 The fr Unit and minmax()

The fr unit is the heart of CSS Grid. It stands for "fraction", a fraction of the available space.

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
}

Here, the middle column gets twice as much space as the outer ones. No percentage math needed.

It gets even more powerful with minmax():

.container {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) 2fr minmax(150px, 1fr);
}

The outer columns are at least 200px and 150px wide, but they grow with available space. That's responsive design without a single media query.

🗺️ Grid Areas: Define Layouts Visually

Now it gets really cool. With grid-template-areas you can literally "draw" your layout:

.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header  header"
    "sidebar content aside"
    "footer  footer  footer";
  gap: 1rem;
}

header  { grid-area: header; }
nav     { grid-area: sidebar; }
main    { grid-area: content; }
aside   { grid-area: aside; }
footer  { grid-area: footer; }

You can see the layout right in the code. It's like a blueprint. Everyone on the team instantly understands what's going on.

🔄 auto-fill vs. auto-fit: Responsive Without Media Queries

Here are two keywords that will make your life significantly easier:

/* auto-fill: Creates as many columns as possible */
.grid-fill {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1rem;
}

/* auto-fit: Like auto-fill, but empty columns collapse */
.grid-fit {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1rem;
}

The difference? With auto-fill, empty columns remain as placeholders. With auto-fit, they collapse and existing elements stretch out.

For most card grids, you want auto-fit. Try it out!

🎯 gap, place-items, and place-content

Spacing and alignment, the seasoning on your Grid dish.

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem; /* Space between all cells */

  /* Center elements within their cell */
  place-items: center;

  /* Center the entire grid within the container */
  place-content: center;
}

place-items is shorthand for align-items + justify-items. place-content is shorthand for align-content + justify-content. Less code, same effect.

🏷️ Named Grid Lines

You can give your grid lines names. This makes your code way more readable, especially in complex layouts.

.container {
  display: grid;
  grid-template-columns:
    [sidebar-start] 250px
    [sidebar-end content-start] 1fr
    [content-end aside-start] 300px
    [aside-end];
  grid-template-rows:
    [header-start] auto
    [header-end main-start] 1fr
    [main-end footer-start] auto
    [footer-end];
}

.sidebar {
  grid-column: sidebar-start / sidebar-end;
  grid-row: main-start / main-end;
}

Instead of cryptic numbers like grid-column: 1 / 2, you just say where the element should go. Your future self will thank you.

🆕 Subgrid: The Newest Superpower

Subgrid is a game-changer. It lets nested grids inherit the column or row definitions of their parent grid.

.parent {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

.child {
  grid-column: span 4;
  display: grid;
  grid-template-columns: subgrid;
  /* Inherits the 4 columns from the parent grid */
}

Why does this matter? Imagine card layouts where the title, image, and button across all cards need to be perfectly aligned. Without subgrid, that was a nightmare. With subgrid, it's trivial.

Subgrid now has broad browser support, all modern browsers handle it just fine.

Container Queries in CSS: The End of Media Queries? 📦
Grid + Container Queries = ultimate responsive power. Check it out!

🛠️ Practical Examples

Dashboard Layout

.dashboard {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 60px 1fr;
  grid-template-areas:
    "nav header"
    "nav main";
  height: 100vh;
  gap: 0;
}

.dashboard-nav    { grid-area: nav; background: #1a1a2e; }
.dashboard-header { grid-area: header; background: #16213e; }
.dashboard-main   { grid-area: main; padding: 2rem; }

/* Cards within the main area */
.dashboard-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.5rem;
}

Card Grid with Even Heights

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 2rem;
}

.card {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3; /* Image, Content, Footer */
}

Holy Grail Layout

.holy-grail {
  display: grid;
  grid-template:
    "header header header" auto
    "nav    main   aside"  1fr
    "footer footer footer" auto
    / 200px 1fr    200px;
  min-height: 100vh;
  gap: 1rem;
}

header { grid-area: header; }
nav    { grid-area: nav; }
main   { grid-area: main; }
aside  { grid-area: aside; }
footer { grid-area: footer; }

The Holy Grail layout, the holy grail of web design for years, is a five-liner with Grid. No float hacks, no clearfix, no duct tape.

🧭 When Grid, When Flexbox?

Situation Recommendation
Navigation / Toolbar Flexbox
Page layout with header, sidebar, content Grid
Card grid Grid
Centering elements Either works
Elements in a row with variable width Flexbox
Complex, nested layouts Grid (with Subgrid)
Dynamic alignment on a single axis Flexbox

The golden rule: Grid for the layout, Flexbox for the components. Sure, there are gray areas, but this rule of thumb will serve you right 90% of the time.

CSS Grid Layout - CSS: Cascading Style Sheets | MDN
The official MDN reference for CSS Grid – perfect for looking things up.
A Complete Guide to CSS Grid | CSS-Tricks
The ultimate visual guide to CSS Grid from CSS-Tricks.

💡 Conclusion

CSS Grid isn't a replacement for Flexbox, it's the perfect complement. If you've only been using Flexbox, you're literally missing half of CSS's layout power.

Start with grid-template-areas. That's the most intuitive entry point. Then work your way to auto-fit + minmax(). And once you discover subgrid, you'll wonder how you ever lived without it.

Grid + Flexbox together = layout superpowers. No framework needed. Just pure CSS. 🚀