CSS Grid — The Complete Guide

The ultimate two-dimensional layout solution. From Grid fundamentals to responsive best practices, master the core of modern CSS layout.

CSS Grid is the first truly two-dimensional layout system. Unlike Flexbox, which handles a single axis (row or column), Grid can control both rows and columns simultaneously, making complex layouts simple and intuitive. This guide covers Grid's core concepts, real-world patterns, and how to choose between Grid and Flexbox.

1. Grid vs Flexbox: How to Choose?

🔵 Use Flexbox

  • One-dimensional layout (single row or column)
  • Navigation bars, toolbars
  • Internal card element arrangement
  • Form row alignment
  • When content direction is uncertain
  • When content should drive sizing

🟣 Use Grid

  • Two-dimensional layout (rows + columns)
  • Overall page structure
  • Card grids / image galleries
  • Dashboard layouts
  • Precise area division needed
  • Items spanning multiple rows/columns
💡 Golden rule: Grid defines the page "skeleton," Flexbox handles component "flesh and blood." They work best together.

2. Basic Syntax

Creating a Grid Container

.grid-container {
  display: grid;
  grid-template-columns: 200px 200px 200px;  /* Three equal columns */
  grid-template-rows: 100px 100px;            /* Two equal rows */
  gap: 16px;
}

The fr Unit

fr (fraction) is Grid's unique flexible unit, representing equal shares of remaining space:

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

/* Sidebar + main content */
grid-template-columns: 250px 1fr;

/* Complex ratio */
grid-template-columns: 2fr 1fr 1fr;  /* 2:1:1 */

/* Mixed fixed and flexible */
grid-template-columns: 200px 1fr 200px;

repeat() Function

/* Equivalent to 1fr 1fr 1fr 1fr */
grid-template-columns: repeat(4, 1fr);

/* Repeating pattern */
grid-template-columns: repeat(3, 1fr 2fr);  /* 1fr 2fr 1fr 2fr 1fr 2fr */

/* auto-fill responsive */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

3. auto-fill vs auto-fit

This is one of the most confusing concepts in Grid. Both work with minmax() to create responsive column counts:

/* auto-fill: preserves empty tracks */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

/* auto-fit: collapses empty tracks, items stretch to fill */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
💡 Practical advice: For most card grid scenarios, auto-fit works better—items stretch when few and wrap when many. Use auto-fill when you need items to maintain a fixed width.

4. Grid Areas (Named Areas)

One of Grid's most powerful features is named areas, which let you define layouts with intuitive "ASCII art" syntax:

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

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

Named areas make layout code as intuitive as "drawing"—easy to read, maintain, and modify.

5. Spanning Rows and Columns

/* Span 2 columns */
.featured { grid-column: span 2; }

/* Span 2 rows */
.sidebar { grid-row: span 2; }

/* Specify exact position */
.highlight {
  grid-column: 1 / 3;    /* From line 1 to line 3 */
  grid-row: 2 / 4;        /* From line 2 to line 4 */
}

6. Alignment

Grid's alignment properties are similar to Flexbox but with two dimensions:

.grid-container {
  /* Item alignment within cells */
  justify-items: center;   /* Horizontal */
  align-items: center;     /* Vertical */
  place-items: center;     /* Shorthand: both directions */

  /* Grid alignment within container */
  justify-content: center;  /* Horizontal */
  align-content: center;    /* Vertical */
  place-content: center;    /* Shorthand */
}

/* Individual item alignment */
.special-item {
  justify-self: end;
  align-self: start;
  place-self: end start;  /* Shorthand */
}

7. Responsive Layout Best Practices

1. Auto-fit Card Grid (Most Common Pattern)

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

/* No media queries needed! Automatically adapts:
   Large screen: 4–5 columns
   Medium screen: 2–3 columns
   Small screen: 1 column
*/

2. Responsive Page Layout

/* Default: single column (mobile) */
.layout {
  display: grid;
  grid-template-areas:
    "header"
    "nav"
    "main"
    "aside"
    "footer";
  gap: 1rem;
}

/* Tablet and above */
@media (min-width: 768px) {
  .layout {
    grid-template-areas:
      "header header"
      "nav    main"
      "aside  main"
      "footer footer";
    grid-template-columns: 200px 1fr;
  }
}

/* Desktop and above */
@media (min-width: 1024px) {
  .layout {
    grid-template-areas:
      "header header header"
      "nav    main   aside"
      "footer footer footer";
    grid-template-columns: 200px 1fr 250px;
  }
}

3. clamp() / max() / min() with Grid

/* Limit column width range */
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));

/* Use clamp for gap control */
gap: clamp(0.5rem, 2vw, 2rem);

/* max() ensures sidebar doesn't shrink below a threshold */
grid-template-columns: max(200px, 20%) 1fr;

8. subgrid

Subgrid allows child elements to inherit the parent grid's track definitions, enabling cross-level alignment:

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

.child-card {
  grid-column: span 3;
  display: grid;
  grid-template-columns: subgrid;  /* Inherits parent's 3 columns */
}

/* Elements inside child-card auto-align with parent columns */
💡 Compatibility: Subgrid is supported in Chrome 117+, Firefox 71+, and Safari 16+. For unsupported browsers, provide a fallback layout.

9. Grid + Flexbox Hybrid Layout

/* Grid controls page structure */
.page {
  display: grid;
  grid-template-columns: 280px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  min-height: 100vh;
}

/* Flexbox handles component internals */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

10. Recommended Tools

FAQ

What's the difference between auto-fill and auto-fit?

When items don't fill the container, auto-fill preserves empty grid tracks (placeholders), while auto-fit collapses empty tracks to 0 width, stretching items to fill the space. When items are sufficient to fill the container, both produce identical results.

Can CSS Grid replace Flexbox?

Not entirely. Grid excels at two-dimensional layout (controlling rows and columns simultaneously), while Flexbox excels at one-dimensional layout (arranging content in a single row or column). Best practice is to use both together: Grid for page structure, Flexbox for component internals.