DEV Community

楊東霖
楊東霖

Posted on • Originally published at devtoolkit.cc

CSS Grid Layout: Complete Tutorial with Examples

CSS Grid is the most powerful layout system available in CSS. Unlike Flexbox, which is one-dimensional, Grid handles both rows and columns simultaneously, making it ideal for complex page layouts. Once you understand Grid's mental model, you'll find yourself reaching for it constantly — and wondering how you ever designed without it.

The Grid Mental Model

A CSS Grid layout consists of:

  • A grid container — the parent with display: grid
  • Grid items — direct children of the container
  • Grid tracks — the rows and columns that define the grid structure
  • Grid lines — the dividing lines between tracks (numbered from 1)
  • Grid cells — the intersection of a row and column
  • Grid areas — named rectangular regions spanning one or more cells

Defining a Grid

grid-template-columns and grid-template-rows

These properties define the track sizes. Values can be lengths, percentages, fr units (fractions of available space), or the auto keyword.

.container {
  display: grid;

  /* Three equal columns */
  grid-template-columns: 1fr 1fr 1fr;

  /* Shorthand with repeat() */
  grid-template-columns: repeat(3, 1fr);

  /* Mixed sizes: fixed sidebar, flexible content, fixed sidebar */
  grid-template-columns: 200px 1fr 200px;

  /* Two rows: auto height, then 100px */
  grid-template-rows: auto 100px;

  /* Minimum 120px, grows to fit content */
  grid-template-rows: minmax(120px, auto);
}
Enter fullscreen mode Exit fullscreen mode

The fr unit is the key to Grid. It represents a fraction of the available space after fixed-size tracks are accounted for. 1fr 2fr 1fr creates three columns where the middle takes twice the space of the outer ones.

gap

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;           /* same for rows and columns */
  row-gap: 16px;       /* or set separately */
  column-gap: 24px;
}
Enter fullscreen mode Exit fullscreen mode

repeat() and minmax()

/* repeat(count, size) */
grid-template-columns: repeat(4, 1fr);      /* 4 equal columns */
grid-template-columns: repeat(4, 200px);    /* 4 fixed-width columns */

/* minmax(min, max) — useful for responsive grids */
grid-template-columns: repeat(3, minmax(200px, 1fr));

/* auto-fill vs auto-fit with minmax — responsive without media queries */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-template-columns: repeat(auto-fit,  minmax(200px, 1fr));
Enter fullscreen mode Exit fullscreen mode

auto-fill creates as many tracks as will fit, even if some are empty. auto-fit collapses empty tracks, letting filled tracks expand. For most responsive grids, auto-fit is what you want.

Placing Items on the Grid

grid-column and grid-row

Items are placed using line numbers. Grid lines are numbered starting from 1, and negative numbers count from the end.

.item {
  /* span from line 1 to line 3 (2 columns wide) */
  grid-column: 1 / 3;

  /* span from line 2 to line 4 */
  grid-column: 2 / 4;

  /* use span keyword */
  grid-column: 1 / span 2;   /* start at 1, span 2 columns */
  grid-column: span 3;        /* auto-placed, but 3 columns wide */

  /* last column using negative index */
  grid-column: 1 / -1;       /* full width */

  /* rows */
  grid-row: 1 / 3;           /* span 2 rows tall */
}
Enter fullscreen mode Exit fullscreen mode

grid-area

grid-area is shorthand for row-start / column-start / row-end / column-end:

.item {
  /* grid-area: row-start / col-start / row-end / col-end */
  grid-area: 1 / 1 / 3 / 4;
}
Enter fullscreen mode Exit fullscreen mode

Named Grid Areas

Named areas are the most readable way to define complex layouts. Use grid-template-areas on the container and grid-area on items.

.layout {
  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";
  min-height: 100vh;
  gap: 16px;
}

header  { grid-area: header;  }
.sidebar { grid-area: sidebar; }
main    { grid-area: content; }
aside   { grid-area: aside;   }
footer  { grid-area: footer;  }
Enter fullscreen mode Exit fullscreen mode

Each string in grid-template-areas represents a row. Cells with the same name form a rectangular area. Use a period (.) for empty cells.

.layout {
  grid-template-areas:
    "header header header"
    "sidebar content ."     /* empty cell in last column */
    "footer footer footer";
}
Enter fullscreen mode Exit fullscreen mode

Alignment

Container-level alignment

justify-items and align-items control how items are aligned within their grid cells.

.container {
  /* Horizontal alignment of items within cells */
  justify-items: start | end | center | stretch; /* default: stretch */

  /* Vertical alignment of items within cells */
  align-items: start | end | center | stretch;   /* default: stretch */

  /* Shorthand */
  place-items: center;           /* center both axes */
  place-items: start end;        /* align-items start, justify-items end */
}
Enter fullscreen mode Exit fullscreen mode

justify-content and align-content control how the entire grid is distributed within the container (when the grid is smaller than the container).

.container {
  justify-content: start | end | center | space-between | space-around | space-evenly;
  align-content: start | end | center | space-between | space-around | space-evenly;
  place-content: center; /* shorthand */
}
Enter fullscreen mode Exit fullscreen mode

Item-level alignment

.item {
  justify-self: start | end | center | stretch;
  align-self: start | end | center | stretch;
  place-self: center; /* shorthand */
}
Enter fullscreen mode Exit fullscreen mode

Auto-Placement

Items that aren't explicitly placed are auto-placed into the grid. grid-auto-flow controls how auto-placement works.

.container {
  grid-auto-flow: row;         /* default: fill rows first */
  grid-auto-flow: column;      /* fill columns first */
  grid-auto-flow: row dense;   /* fill holes with smaller items */
  grid-auto-flow: column dense;
}

/* grid-auto-rows / grid-auto-columns: set implicit track sizes */
.container {
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto); /* any implicit rows default to this */
}
Enter fullscreen mode Exit fullscreen mode

The dense keyword is great for masonry-like layouts — it packs items into any available gaps.

Real-World Layout Patterns

Responsive Card Grid (No Media Queries)

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
  padding: 24px;
}
Enter fullscreen mode Exit fullscreen mode

This single rule creates a responsive grid that shows as many columns as fit, each at least 280px wide. No media queries needed.

Full-Page App Layout

.app {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr;
  grid-template-areas:
    "sidebar topbar"
    "sidebar content";
  height: 100vh;
}

.sidebar { grid-area: sidebar; overflow-y: auto; }
.topbar  { grid-area: topbar;  }
.content { grid-area: content; overflow-y: auto; }

/* Responsive: collapse sidebar on mobile */
@media (max-width: 768px) {
  .app {
    grid-template-columns: 1fr;
    grid-template-rows: 64px auto 1fr;
    grid-template-areas:
      "topbar"
      "sidebar"
      "content";
  }
}
Enter fullscreen mode Exit fullscreen mode

Magazine Layout

.magazine {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
}

.featured-article {
  grid-column: 1 / 4;  /* spans 3 columns */
  grid-row: 1 / 3;     /* spans 2 rows */
}

.secondary-article {
  grid-column: 4 / 7;  /* spans last 3 columns */
}

.sidebar-widget {
  grid-column: 4 / 7;
  grid-row: 2;
}
Enter fullscreen mode Exit fullscreen mode

Image Gallery with Large Feature Image

.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 200px;
  gap: 8px;
}

.gallery-item:first-child {
  grid-column: 1 / 3;   /* featured: 2 columns wide */
  grid-row: 1 / 3;      /* and 2 rows tall */
}
Enter fullscreen mode Exit fullscreen mode

Centering a Single Item

.page {
  display: grid;
  place-items: center;
  min-height: 100vh;
}
Enter fullscreen mode Exit fullscreen mode

Grid vs Flexbox: When to Use Which

  • Use Grid when you need a two-dimensional layout — rows AND columns must align. Page layouts, data tables, image galleries.
  • Use Flexbox when you're distributing items along a single axis — a row of buttons, a nav bar, a vertical list.
  • They're designed to work together: Grid for macro layout, Flexbox for micro-components within grid cells.

Subgrid

Subgrid (CSS Grid Level 2, now supported in all modern browsers) lets a nested grid inherit tracks from its parent, enabling precise alignment across components.

.parent {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.child {
  display: grid;
  grid-column: span 2;
  grid-template-columns: subgrid; /* inherit parent columns */
}
Enter fullscreen mode Exit fullscreen mode

Quick Reference

/* Container */
display: grid | inline-grid
grid-template-columns: <track-sizes>
grid-template-rows: <track-sizes>
grid-template-areas: "..." "..."
gap: <row> <col>
grid-auto-flow: row | column | dense
grid-auto-rows: <size>
grid-auto-columns: <size>
justify-items: start | end | center | stretch
align-items: start | end | center | stretch
place-items: <align> <justify>
justify-content: start | end | center | space-*
align-content: start | end | center | space-*

/* Items */
grid-column: <start> / <end>
grid-row: <start> / <end>
grid-area: <name> | <row-start> / <col-start> / <row-end> / <col-end>
justify-self: start | end | center | stretch
align-self: start | end | center | stretch
place-self: <align> <justify>

/* Useful functions */
repeat(count, size)
minmax(min, max)
fit-content(size)
auto-fill / auto-fit
Enter fullscreen mode Exit fullscreen mode

CSS Grid is worth spending a few hours experimenting with. Create a simple page layout, try named grid areas, then build a responsive card grid without any media queries. Once it clicks, you'll never go back to float-based layouts or complex Flexbox hacks for two-dimensional problems.

Free Developer Tools

If you found this article helpful, check out DevToolkit — 40+ free browser-based developer tools with no signup required.

Popular tools: JSON Formatter · Regex Tester · JWT Decoder · Base64 Encoder

🛒 Get the DevToolkit Starter Kit on Gumroad — source code, deployment guide, and customization templates.

Top comments (0)