HTML & CSS: The Document Model•Layout Systems•Lesson 10 of 18

CSS Grid

Grid is a two-dimensional layout system. Define rows and columns, then place items into the resulting cells. Unlike flexbox, which flows in one direction, grid controls both axes simultaneously.

Grid solves the layout problems that required complex float and positioning hacks: magazine layouts, asymmetric designs, overlapping content.

The Grid Container

Apply display: grid to a parent element. Its direct children become grid items.

.layout {
  display: grid;
}

Without further properties, items stack vertically in a single column. You need to define the grid structure.

Grid Template Columns and Rows

Define column widths with grid-template-columns and row heights with grid-template-rows.

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

This creates a three-column layout: fixed sidebars with a flexible center.

The Fr Unit

The fr unit represents a fraction of available space. Use it instead of percentages.

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

The middle column is twice as wide as the sides. Grid calculates sizes after fixed and minimum constraints.

Why not percentages?

/* Percentages don't account for gaps */
.bad {
  grid-template-columns: 33.333% 33.333% 33.333%;
  gap: 1rem; /* now columns overflow */
}

/* Fr units handle gaps correctly */
.good {
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1rem; /* columns fit perfectly */
}

Repeat Function

Don't type the same value repeatedly.

/* Repetitive */
.grid {
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}

/* Clean */
.grid {
  grid-template-columns: repeat(5, 1fr);
}

Mix repeat with other values:

.layout {
  grid-template-columns: 250px repeat(3, 1fr) 250px;
}

Auto-Fill and Auto-Fit

Create responsive grids without media queries.

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1rem;
}
  • auto-fill: Creates as many columns as fit, even if empty
  • auto-fit: Creates columns only for content, collapses empty ones

Use auto-fit for cards and galleries. Items expand to fill available space.

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

Minmax Function

Set minimum and maximum sizes for tracks.

.grid {
  grid-template-columns: minmax(200px, 300px) 1fr;
}

The first column is never smaller than 200px or larger than 300px.

Common pattern for responsive content:

.container {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

The minmax(0, 1fr) prevents grid items from overflowing. By default, grid items won't shrink below their content size. Setting minimum to 0 allows shrinking.

Grid Lines and Placement

Grid creates numbered lines between tracks. Use them to place items.

.item {
  grid-column: 1 / 3; /* spans from line 1 to line 3 */
  grid-row: 1 / 2;
}

Shorthand with span:

.item {
  grid-column: span 2; /* spans 2 columns */
}

Negative numbers count from the end:

.full-width {
  grid-column: 1 / -1; /* start to end */
}

Grid Template Areas

Name regions of your grid for semantic placement.

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

.header {
  grid-area: header;
}

.sidebar {
  grid-area: sidebar;
}

.main {
  grid-area: main;
}

.aside {
  grid-area: aside;
}

.footer {
  grid-area: footer;
}

The ASCII-art structure makes the layout obvious. Change it at a breakpoint:

@media (max-width: 768px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main"
      "sidebar"
      "aside"
      "footer";
  }
}

Implicit Grid

When items exceed defined rows/columns, grid creates implicit tracks.

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* only defined columns, no rows */
}

If you add 10 items, grid creates rows automatically. Control their size:

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px; /* implicit rows are 200px */
}

Use minmax for flexible implicit rows:

.grid {
  grid-auto-rows: minmax(150px, auto);
}

Alignment

Grid has alignment properties similar to flexbox.

.grid {
  display: grid;
  justify-items: center; /* align items horizontally */
  align-items: center; /* align items vertically */
}

Align the entire grid within its container:

.container {
  display: grid;
  grid-template-columns: repeat(3, 200px);
  justify-content: center; /* center the grid horizontally */
  gap: 1rem;
}

Individual items override with justify-self and align-self:

.special {
  justify-self: end;
  align-self: start;
}

Gap

Space between grid cells. Works like flexbox gap.

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

Different row and column gaps:

.grid {
  row-gap: 2rem;
  column-gap: 1rem;
}

Subgrid

A grid item can inherit column or row tracks from its parent grid.

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

.child {
  display: grid;
  grid-column: span 4;
  grid-template-columns: subgrid; /* inherit parent's 4 columns */
}

Useful for aligning nested content to the parent grid structure.

Grid vs Flexbox Decision Framework

Use Grid when:

  • You need precise 2D control (rows AND columns)
  • Layout is container-defined (you decide structure)
  • Items need to align across rows/columns
  • Overlapping content
  • Complex page layouts

Use Flexbox when:

  • One-dimensional arrangement
  • Content size determines layout
  • Navigation, button groups, toolbars
  • Centering, space distribution
  • Flexible ordering

Sometimes you'll use both:

/* Grid for page layout */
.page {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}

/* Flexbox for header content */
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

Practical Example: Card Grid

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

.card {
  display: grid;
  grid-template-rows: 200px auto 1fr auto;
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
}

.card-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-title {
  padding: 1rem;
  font-size: 1.25rem;
  font-weight: 600;
}

.card-content {
  padding: 0 1rem;
}

.card-actions {
  padding: 1rem;
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
}
<div class="cards">
  <article class="card">
    <img src="image1.jpg" class="card-image" alt="">
    <h3 class="card-title">Card Title</h3>
    <div class="card-content">
      <p>Card description goes here.</p>
    </div>
    <div class="card-actions">
      <button>Read More</button>
    </div>
  </article>
  <!-- more cards -->
</div>

The outer grid creates responsive columns. Each card uses grid internally to ensure consistent heights and button alignment.

Check Your Understanding

What's the difference between auto-fit and auto-fill in repeat()?

Not quite. The correct answer is highlighted.

Which unit automatically accounts for gap spacing?

Not quite. The correct answer is highlighted.
To make a grid item span from the first to the last column, use grid-column: 1 /
Not quite.Expected: -1

Practice

Summary

  • Two-dimensional: Control rows and columns simultaneously
  • Grid container: display: grid makes direct children grid items
  • Fr unit: Represents fraction of available space, handles gaps correctly
  • Repeat: repeat(count, size) avoids repetition
  • Auto-fit/auto-fill: Responsive columns without media queries
  • Minmax: Set minimum and maximum track sizes
  • Grid lines: Numbered lines between tracks for precise placement
  • Template areas: Named regions for semantic layout
  • Implicit grid: Auto-created rows/columns for overflow content
  • Gap: Spacing between cells, cleaner than margins
  • Subgrid: Inherit parent grid tracks for nested alignment
  • Use grid for: 2D layouts, galleries, page structure, overlapping content
  • Use flexbox for: 1D layouts, navigation, button groups, content flow

Keep Practicing

Grid Garden — A game where you grow a carrot garden by writing CSS grid code