CSS Reference Guide

All TopicsPlayground

CSS Grid

CSS Grid Layout is a two-dimensional layout system that handles both columns and rows simultaneously. It is the most powerful layout system in CSS.

LayoutTwo-DimensionalEssentialModern

Display Grid

Setting display: grid on a container creates a grid container. Its direct children become grid items that can be placed into rows and columns.

CSS
.container {
  display: grid;          /* block-level grid container */
}

.container-inline {
  display: inline-grid;   /* inline-level grid container */
}
Grid Terminology

Grid Line: the dividing lines that make up the structure. Grid Track: the space between two adjacent lines (a column or row). Grid Cell: a single unit of the grid. Grid Area: a rectangular area spanning one or more cells.

Grid Template Columns

Defines the number and size of columns in your grid. You can use fixed units, fractions, percentages, or any combination.

CSS
.grid {
  display: grid;

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

  /* Fractional units — equal columns */
  grid-template-columns: 1fr 1fr 1fr;

  /* Mixed units */
  grid-template-columns: 250px 1fr 2fr;

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

  /* Percentage-based */
  grid-template-columns: 25% 50% 25%;
}
Live Example — Fixed Pixel Columns: 100px 200px 100px
100px
200px
100px

Fractional Columns: 1fr 2fr 1fr

1fr
2fr
1fr

Mixed: 200px 1fr 1fr

200px (fixed)
1fr (flexible)
1fr (flexible)

Grid Template Rows

Defines the size of rows in the grid. Works identically to grid-template-columns but along the vertical axis.

CSS
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 100px 200px 100px;  /* 3 rows */
}

/* Common pattern: header, flexible content, footer */
.page-grid {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}
Live Example — Explicit Row Sizes
60px row
60px row
100px row
100px row
60px row
60px row

The fr Unit Deep Dive

The fr (fraction) unit represents a fraction of the available space in the grid container. It distributes space after fixed-size tracks and gaps are calculated.

CSS
/* Container is 900px wide, gap is 10px */
.grid {
  display: grid;
  grid-template-columns: 200px 1fr 2fr;
  gap: 10px;
  /*
    Available space = 900 - 200 - (10 * 2) = 680px
    1fr = 680 / 3 = ~227px
    2fr = 680 * 2/3 = ~453px
  */
}
Live Example — How fr Distributes Space

200px is fixed, remaining space split 1:2

200px (fixed)
1fr
2fr
fr vs percentage

fr distributes available space (after gaps and fixed tracks), while % is based on total container width. With gaps, percentages can overflow; fr never will. Always prefer fr in grid layouts.

repeat() Function

The repeat() function provides a shorthand for repeating track patterns. Saves typing and makes intent clearer.

CSS
.grid {
  /* Instead of: 1fr 1fr 1fr 1fr */
  grid-template-columns: repeat(4, 1fr);

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

  /* Responsive: auto-fit fills available space */
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

  /* Responsive: auto-fill preserves empty tracks */
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
Live Example — repeat(4, 1fr)
1
2
3
4

minmax()

The minmax() function sets a minimum and maximum size for a grid track. Essential for responsive grids.

CSS
.grid {
  display: grid;

  /* Column: at least 200px, at most 1fr */
  grid-template-columns: minmax(200px, 1fr) 2fr;

  /* Rows: at least 100px, grow with content */
  grid-template-rows: minmax(100px, auto);

  /* The responsive grid pattern */
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
Live Example — minmax(150px, 1fr) Responsive Cards
Card 1
min 150px
Card 2
min 150px
Card 3
min 150px
Card 4
min 150px

Resize the browser to see cards reflow automatically.

auto-fit vs auto-fill

Both create as many tracks as possible, but they differ when there are fewer items than tracks.

CSS
/* auto-fit: collapses empty tracks, items stretch */
.grid-fit {
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

/* auto-fill: keeps empty tracks, items don't stretch */
.grid-fill {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
Live Example — auto-fit vs auto-fill (Side by Side)

auto-fit: items stretch to fill the row

Item 1
Item 2

auto-fill: empty tracks preserved, items stay at min size

Item 1
Item 2

Notice how auto-fit stretches the 2 items across the full width, while auto-fill leaves space for empty columns.

Which one to use?

Use auto-fit for most cases — items stretch to fill the container. Use auto-fill when you want items to maintain their minimum size and leave empty space on the right.

Gap

Sets spacing between grid rows and columns. Same property as in flexbox.

CSS
.grid {
  gap: 1rem;                   /* equal row and column gaps */
  row-gap: 2rem;               /* gap between rows */
  column-gap: 1rem;            /* gap between columns */
  gap: 2rem 1rem;               /* row-gap column-gap */
}
Live Example — gap: 1.5rem 0.75rem (row column)
1
2
3
4
5
6

Larger row gap (1.5rem) and smaller column gap (0.75rem).

Grid Template Areas

The most visual way to define a grid layout. Name areas with grid-template-areas and assign items with grid-area.

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

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer  { grid-area: footer; }
Live Example — Full Page Layout with grid-template-areas
Header
Sidebar
Nav Item 1
Nav Item 2
Nav Item 3
Main Content
This area takes all remaining space thanks to the 1fr column and 1fr row.
Footer
Empty Cells

Use a dot (.) in grid-template-areas to leave a cell empty: "header ." — the second column in that row will be blank.

Grid Placement (grid-column / grid-row / span)

Place items on specific grid lines or make them span multiple tracks using line numbers.

CSS
.item {
  /* By line numbers */
  grid-column: 1 / 3;       /* start at line 1, end at line 3 */
  grid-row: 1 / 2;          /* start at line 1, end at line 2 */

  /* Using span */
  grid-column: span 2;       /* span 2 columns from default position */
  grid-row: span 3;          /* span 3 rows */

  /* Start at line 2, span 2 columns */
  grid-column: 2 / span 2;

  /* Full width: start to end */
  grid-column: 1 / -1;      /* -1 = last line */
}

/* Shorthand: grid-area: row-start / col-start / row-end / col-end */
.item {
  grid-area: 1 / 1 / 3 / 4;  /* rows 1-3, columns 1-4 */
}
Live Example — Spanning Items
grid-column: 1 / -1 (full width)
span 2
1 col
1 col
1 col
span 3

Named Lines

Give meaningful names to grid lines for more readable placement.

CSS
.grid {
  display: grid;
  grid-template-columns:
    [full-start] 1fr
    [content-start] 3fr
    [content-end] 1fr
    [full-end];
}

.hero {
  grid-column: full-start / full-end;   /* spans everything */
}
.article {
  grid-column: content-start / content-end;  /* centered content */
}
Live Example — Named Grid Lines
Hero (full-start / full-end)
Article (content-start / content-end)
Banner (full-start / full-end)

Implicit Grid

When items are placed outside the explicit grid, the browser creates implicit tracks. Control their size with grid-auto-rows, grid-auto-columns, and grid-auto-flow.

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

  /* Size of auto-created rows */
  grid-auto-rows: 150px;
  grid-auto-rows: minmax(100px, auto);  /* at least 100px, grows with content */

  /* Control flow direction */
  grid-auto-flow: row;        /* default — fill rows first */
  grid-auto-flow: column;     /* fill columns first */
  grid-auto-flow: dense;      /* fill holes in the grid */
  grid-auto-flow: row dense;  /* row order, backfill gaps */
}
Live Example — grid-auto-rows: minmax(60px, auto)
Short
Also short
Short
This cell has more content so the entire row grows taller to accommodate it automatically.
Same row
Same row
grid-auto-flow: dense

The dense packing algorithm backfills empty cells in the grid. Great for masonry-like layouts where you have items of varying sizes. Note that it may reorder items visually.

Alignment

Grid has 6 alignment properties — they control how items are placed within their grid cells and how tracks are distributed within the container.

CSS
/* Container properties — align ALL items */
.grid {
  /* Align items within their cell (inline/row axis) */
  justify-items: start | end | center | stretch;

  /* Align items within their cell (block/column axis) */
  align-items: start | end | center | stretch;

  /* Distribute tracks in container (inline axis) */
  justify-content: start | end | center | space-between | space-around | space-evenly;

  /* Distribute tracks in container (block axis) */
  align-content: start | end | center | space-between | space-around | space-evenly;

  /* Shorthand: place-items = align-items justify-items */
  place-items: center;
  /* Shorthand: place-content = align-content justify-content */
  place-content: center;
}

/* Item properties — override alignment for ONE item */
.item {
  justify-self: start | end | center | stretch;
  align-self: start | end | center | stretch;
  place-self: center;
}
Live Example — place-items: center (Centers Everything)
Centered
Centered
Centered

Each item is centered within its grid cell.

Live Example — Individual Alignment with justify-self / align-self
start / start
center / center
end / end

Real-World Layouts

Responsive Card Grid

CSS
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
}
Live Example — Responsive Card Grid
Card Title

Auto-responsive without media queries.

Card Title

Uses auto-fit + minmax pattern.

Card Title

Resize the browser to see reflow.

Dashboard Layout

CSS
.dashboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: minmax(120px, auto);
  gap: 1rem;
}
.widget-large  { grid-column: span 2; grid-row: span 2; }
.widget-wide   { grid-column: span 2; }
Live Example — Dashboard Grid
2,450
Total Users (span 2x2)
89%
Uptime
340
Orders
Wide Widget (span 2)

Magazine Layout

CSS
.magazine {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px;
  gap: 1rem;
}
.featured {
  grid-column: span 2;
  grid-row: span 2;
}
Live Example — Magazine Layout
Featured Article
The big story takes the spotlight
Article 2
Article 3
Article 4
Article 5
Article 6

Grid vs Flexbox

They are complementary, not competing. Use both together for the best layouts.

Feature Flexbox Grid
Dimensions One-dimensional (row OR column) Two-dimensional (rows AND columns)
Approach Content-first (items determine layout) Layout-first (grid defines the structure)
Best for Components (navbars, card internals) Page layouts, card grids
Item placement Sequential (source order) Anywhere on the grid
Gap support Yes Yes
Overlap items No (not natively) Yes (items can occupy same cells)
Dynamic # of items Handles naturally Use auto-fit / auto-fill
The Best Practice

Use Grid for the overall page structure and macro layouts. Use Flexbox for component internals and one-dimensional alignment. They nest beautifully — a grid item can be a flex container, and vice versa.

Gotchas

Grid items stretch by default

Grid items default to align-items: stretch and justify-items: stretch, meaning they fill their entire cell. If your items look bigger than expected, this is why. Set explicit alignment to override.

repeat(auto-fit/auto-fill) needs minmax()

You cannot use repeat(auto-fit, 1fr) — it must be repeat(auto-fit, minmax(200px, 1fr)). The browser needs a minimum size to calculate how many tracks to create.

Percentage gaps can break layouts

Avoid using percentage values for gap in grid — browser support is inconsistent and calculations can be unpredictable. Use rem, em, or px instead.

Grid areas must form rectangles

grid-template-areas only supports rectangular shapes. L-shaped or T-shaped areas are not valid and will break the layout silently.

min-width: 0 again

Just like flexbox, grid items have min-width: auto by default. Long text or content can overflow grid cells. Fix with min-width: 0 or overflow: hidden.

Pro Tips

The Holy Grail Layout in 5 Lines

A full page layout with header, footer, sidebar, and main content using grid-template-areas is the cleanest solution CSS has ever had for this classic problem.

CSS
body {
  display: grid;
  grid-template: "header header" auto
                  "nav    main"   1fr
                  "footer footer" auto
                  / 250px 1fr;
  min-height: 100vh;
}
Subgrid (Modern Browsers)

subgrid allows a grid item's children to align with the parent grid's tracks. Use grid-template-columns: subgrid or grid-template-rows: subgrid on a grid item that is also a grid container. This solves the card alignment problem beautifully.

CSS
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}
.card {
  display: grid;
  grid-row: span 3;              /* card spans 3 parent rows */
  grid-template-rows: subgrid;   /* aligns to parent row tracks */
}
Debug with Browser DevTools

Both Chrome and Firefox have excellent Grid inspectors. In DevTools, click the grid badge next to any grid container to see an overlay of grid lines, areas, and track names. This is the fastest way to debug grid layouts.

Overlapping Items

Unlike flexbox, grid items can occupy the same cells and overlap. Combined with z-index, this enables creative layouts without absolute positioning.

PreviousFlexbox