X Xerobit

CSS Grid Layout — How to Build Two-Dimensional Layouts

CSS Grid creates two-dimensional layouts with explicit rows and columns. Here's how grid-template-columns, grid-area, auto-fit, and minmax work with practical patterns.

Mian Ali Khalid · · 8 min read
Use the tool
CSS Grid Generator
Visual CSS Grid layout builder. Configure columns, rows, gaps, and named areas. Live preview with copyable CSS output.
Open CSS Grid Generator →

CSS Grid is the most powerful layout system available in CSS. Unlike Flexbox (which is one-dimensional), Grid works in both rows and columns simultaneously. It replaced the floats, tables, and JavaScript-calculated layouts that developers used before 2017.

Use the CSS Grid Generator to build grid layouts visually and copy the generated CSS.

Activating CSS Grid

.container {
  display: grid;
}

Any element with display: grid is a grid container. Its direct children become grid items. Grid doesn’t do anything visible until you define columns and rows.

grid-template-columns

Defines the number and size of columns in the grid:

.container {
  display: grid;
  
  /* Three equal columns: */
  grid-template-columns: 1fr 1fr 1fr;
  
  /* Shorthand with repeat(): */
  grid-template-columns: repeat(3, 1fr);
  
  /* Mixed sizes: */
  grid-template-columns: 200px 1fr 1fr;   /* Fixed sidebar + two flexible columns */
  grid-template-columns: 1fr 2fr 1fr;     /* Center column twice as wide */
  
  /* Responsive with auto-fit: */
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

The fr unit

fr (fraction) represents a fraction of the available space in the grid container — after fixed-width columns have been allocated.

/* Container width: 900px, no gap */
grid-template-columns: 200px 1fr 2fr;
/* 200px sidebar → 700px remaining → 1fr = 233px, 2fr = 467px */

repeat()

repeat(count, size) creates multiple identical columns without repeating yourself:

repeat(4, 1fr)        /* Same as: 1fr 1fr 1fr 1fr */
repeat(3, 200px 1fr)  /* Same as: 200px 1fr 200px 1fr 200px 1fr */
repeat(auto-fit, minmax(250px, 1fr))  /* Responsive — covered below */

grid-template-rows

Same syntax as grid-template-columns, for rows:

.container {
  display: grid;
  grid-template-rows: auto 1fr auto; /* Header: content height, main: flexible, footer: content height */
}

auto means the row height is determined by the tallest item in that row.

gap

Spacing between rows and columns:

.container {
  gap: 24px;           /* Same gap for rows and columns */
  gap: 24px 16px;      /* row-gap: 24px, column-gap: 16px */
  row-gap: 24px;
  column-gap: 16px;
}

Placing items: grid-column and grid-row

By default, items fill grid cells left-to-right, top-to-bottom. You can place items explicitly using line numbers.

Grid line numbers start at 1. A 3-column grid has column lines 1, 2, 3, 4.

.item {
  grid-column: 1 / 3;   /* Spans from column line 1 to line 3 (2 columns wide) */
  grid-row: 1 / 2;      /* Spans row line 1 to 2 (1 row tall) */
  
  /* Shorthand: */
  grid-column: 1 / span 2; /* Start at line 1, span 2 columns */
  grid-column: 2 / -1;     /* Start at line 2, end at last line */
  grid-column: 1 / -1;     /* Full width (all columns) */
}

Named grid areas

For complex layouts, naming grid areas is more readable than line numbers:

.container {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}

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

The grid-template-areas value is a visual map of your layout. Each quoted string is a row. Repeated names span that area. . is an empty cell.

The responsive grid: auto-fit + minmax

This pattern is the most powerful responsive grid technique:

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

What it does:

  • auto-fit: creates as many columns as fit, without creating empty columns
  • minmax(250px, 1fr): each column is at least 250px, at most 1fr of available space

Behavior at different viewport widths (assuming 24px gap and padding):

  • 1200px container → fits 4 columns of 280px each
  • 800px container → fits 3 columns of 250px each
  • 500px container → fits 2 columns of 228px each
  • 280px container → 1 column at full width

Zero media queries needed for this responsive behavior. The grid automatically reflows.

auto-fit vs auto-fill

/* auto-fit: collapses empty columns */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

/* auto-fill: keeps empty columns (placeholder columns remain) */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

The difference matters only when there are fewer items than the grid can fit. With auto-fit, items stretch to fill the remaining space. With auto-fill, empty columns remain, and items don’t stretch past their minmax maximum.

For most content grids (cards, products, blog posts), auto-fit is what you want.

Alignment in Grid

Aligning the grid tracks

.container {
  /* Align columns (horizontal): */
  justify-content: start | end | center | stretch | space-between | space-around | space-evenly;
  
  /* Align rows (vertical): */
  align-content: start | end | center | stretch | space-between | space-around | space-evenly;
}

Aligning items within their cells

.container {
  /* Default: items fill their cells */
  justify-items: start | end | center | stretch;  /* horizontal within cell */
  align-items: start | end | center | stretch;    /* vertical within cell */
}

/* Override for individual items: */
.item {
  justify-self: center;
  align-self: end;
}

Centering in a grid cell

.container {
  display: grid;
  place-items: center; /* Shorthand for align-items + justify-items */
}

place-items: center is the most concise way to center content within each grid cell.

Grid vs Flexbox decision guide

Use Grid whenUse Flexbox when
Two-dimensional layout (rows + columns)One-dimensional layout (row OR column)
You define the layout, content fills inContent defines the layout dimensions
Named areas and explicit placementContent flow with wrapping
Page-level structureComponent-level structure
Newspaper/magazine-style layoutsNavigation bars, button groups, card rows

They work together: use Grid for the overall page layout, Flexbox for the internal layout of components within grid areas.

Common Grid patterns

12-column grid system

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 24px;
}

/* Bootstrap-like column spans: */
.col-4  { grid-column: span 4; }
.col-6  { grid-column: span 6; }
.col-12 { grid-column: span 12; }

Holy grail layout

body {
  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; }

/* Responsive: collapse to single column */
@media (max-width: 768px) {
  body {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main"
      "sidebar"
      "aside"
      "footer";
  }
}

Masonry-like layout

CSS Grid doesn’t yet support true masonry (where items fill in variable-height cells to minimize gaps). A near-masonry effect with fixed row heights:

.masonry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  grid-auto-rows: 8px;     /* Small row unit */
  gap: 16px 16px;
}

.card-short  { grid-row: span 20; }  /* 160px tall */
.card-medium { grid-row: span 30; }  /* 240px tall */
.card-tall   { grid-row: span 45; }  /* 360px tall */

True CSS masonry (masonry value for grid-template-rows) is in the CSS specification but not yet broadly supported in browsers as of 2026.

Using the CSS Grid Generator

The CSS Grid Generator lets you:

  1. Set the number of columns and rows visually
  2. Drag to merge cells and create named areas
  3. Adjust gap, column sizes, and alignment
  4. Copy the complete CSS output

Useful for prototyping layouts before implementing in code, and for learning how different properties interact visually.


Related posts

Related tool

CSS Grid Generator

Visual CSS Grid layout builder. Configure columns, rows, gaps, and named areas. Live preview with copyable CSS output.

Written by Mian Ali Khalid. Part of the Frontend & Design pillar.