Skip to content

CSS Grid: The Complete Guide with Examples

CSS Grid is the most powerful layout system in CSS. It handles both rows and columns simultaneously.

Grid vs Flexbox

FlexboxGrid
One-dimensional (row or column)Two-dimensional (row and column)
Content-drivenLayout-driven
Best for nav bars, centering, componentsBest for page layouts, complex grids

Basic Grid

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

Creates a three-column grid. Each child becomes a grid item.

Grid Template Columns

/* Fixed columns */
grid-template-columns: 200px 200px 200px;

/* Responsive columns */
grid-template-columns: 1fr 2fr 1fr;    /* 3 columns, middle is twice as wide */
grid-template-columns: repeat(3, 1fr);  /* 3 equal columns */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));  /* responsive! */
grid-template-columns: 200px 1fr 200px;  /* fixed + fluid + fixed */

The Responsive Pattern

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1rem;
}

This auto-creates as many 300px-minimum columns as will fit. No media queries needed.

Grid Template Areas

The most readable way to define layouts:

.layout {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar content content"
    "footer  footer  footer";
  grid-template-columns: 200px 1fr 1fr;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer  { grid-area: footer; }

Placing Items Explicitly

.item {
  grid-column: 1 / 3;      /* span from column line 1 to 3 */
  grid-column: 1 / -1;     /* span entire row */
  grid-column: span 2;     /* span 2 columns */

  grid-row: 1 / 3;
  grid-row: span 2;
}

Grid Alignment

.container {
  display: grid;
  grid-template-columns: repeat(3, 100px);

  /* Align all items within their cells */
  justify-items: center;     /* horizontal */
  align-items: center;       /* vertical */

  /* Align the entire grid within the container */
  justify-content: center;   /* horizontal */
  align-content: center;     /* vertical */
}

.item {
  /* Override container alignment for one item */
  justify-self: start;
  align-self: end;
}

Practical Layouts

Holy Grail Layout

body {
  display: grid;
  grid-template:
    "header  header  header" 60px
    "nav     main    aside" 1fr
    "footer  footer  footer" 60px
    / 200px   1fr     200px;
  min-height: 100vh;
}

Card Grid

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

.card {
  display: flex;
  flex-direction: column;
}

.card-footer {
  margin-top: auto;  /* push footer to bottom of card */
}

Dashboard Layout

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

.chart-wide {
  grid-column: span 2;
}

.chart-full {
  grid-column: 1 / -1;
}

Named Grid Lines

.container {
  display: grid;
  grid-template-columns:
    [sidebar-start] 200px
    [sidebar-end content-start] 1fr 1fr
    [content-end];
}

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

.content {
  grid-column: content-start / content-end;
}

Common Gotchas

  • gap replaces grid-gap (deprecated but still works)
  • auto-fill vs auto-fitauto-fill keeps empty tracks, auto-fit collapses them
  • Implicit rows — use grid-auto-rows: minmax(100px, auto) for consistent sizing
  • Overlap — grid items can overlap (positive and negative z-index applies)

Related: Learn Flexbox and responsive design.