DeepFrontend
Practice ArenaBlogSign in
Go Pro
DeepFrontend

Interview-grade learning paths and hands-on practice for mid-to-senior engineers. Master internals, patterns, and system architecture with runnable code.

All systems operational

Core Courses

  • -JavaScript Internals
  • -React Reconciliation
  • -TypeScript rigor
  • -Next.js Caching
  • -Node.js Event Loop
  • -System Design
  • -Web Security
  • -CSS & Page Layouts

Explore

  • Learning Paths
  • Practice Arena
  • Pricing Options
  • HTML Sitemap

Resources

  • Privacy Policy
  • Terms of Service
  • Email Support

© 2026 DeepFrontend. All rights reserved.

Expert learning environments for web engineering teams.

Home/CSS/Grid
beginner25 min read·Updated Jul 2026

Grid

Grid is CSS's native two-dimensional layout system — rows and columns controlled together, with named lines and areas that make complex page layouts readable instead of a nested-div maze.

cssgridlayoutresponsive

Knowledge Check

4 questions · pass at 70%

0/4
easymcq

1. What does the `fr` unit represent in CSS Grid?


Interview Questions

3 questions

Cheatsheet

Download-ready reference
Cheatsheet
display: grid;  →  TWO-dimensional layout — rows AND columns together

Defining tracks:
  grid-template-columns: 200px 1fr 2fr;     fixed + proportional (fr = share of remaining space)
  grid-template-rows: auto 1fr auto;
  gap: 1rem;                                  spacing between all tracks

Responsive grid, zero media queries:
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    auto-fill  → keeps empty tracks (gaps if few items)
    auto-fit   → collapses empty tracks (items stretch to fill)

Placing items (lines are BOUNDARIES, 1-indexed, not the tracks themselves):
  grid-column: 1 / 3;        from line 1 to line 3 = spans 2 tracks
  grid-column: 1 / span 2;   equivalent, clearer intent

Named areas (most readable for complex layouts):
  grid-template-areas:
    "sidebar header"
    "sidebar main"
    "sidebar footer";
  .sidebar { grid-area: sidebar; }

Implicit grid (auto-generated tracks beyond explicit definition):
  grid-auto-rows: 150px;
  grid-auto-flow: row | column | dense;

Subgrid (nested grid inherits parent's actual tracks):
  .child { grid-template-columns: subgrid; }
  → solves "align internal elements across sibling cards" problem

Decision: Grid = 2D (page layout, galleries) | Flexbox = 1D (nav bars, button rows)
→ commonly combined: Grid for skeleton, Flexbox inside individual cells

Related topics

FlexboxResponsive DesignContainer QueriesPro

On this page

25m
Knowledge CheckInterview QuestionsCheatsheet

Concept#

CSS Grid is a two-dimensional layout system — unlike flexbox (one axis at a time), Grid controls rows and columns simultaneously, with items placeable anywhere in that grid by line number, line name, or named area. This makes it the right tool for actual page-level or component-level layouts (a dashboard, a photo gallery, a page with header/sidebar/main/footer) where flexbox would require nested wrapper divs to fake two dimensions.

Defining a grid#

.container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr; /* 3 columns: fixed, then two flexible */
  grid-template-rows: auto 1fr auto;    /* 3 rows: content-sized, flexible, content-sized */
  gap: 1rem;
}

fr (fraction unit) is Grid's most important unit — it represents a share of the remaining space after fixed-size tracks are accounted for. 1fr 1fr splits remaining space equally; 1fr 2fr gives the second column twice the first's share.

repeat() and minmax() — the responsive grid workhorse#

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

This single line creates a fully responsive gallery with zero media queries: as many columns as fit, each at least 200px, growing to fill leftover space equally. auto-fill creates as many tracks as fit (leaving empty tracks if there's extra space); auto-fit collapses empty tracks so existing items stretch to fill the row instead — the difference only matters when there are fewer items than would fill a row.

Placing items explicitly#

.item {
  grid-column: 1 / 3;  /* start at line 1, end at line 3 (spans 2 columns) */
  grid-row: 2 / 4;
  /* shorthand: grid-column: 1 / span 2; is equivalent to 1 / 3 */
}

Grid lines are numbered starting at 1 (not the tracks/cells — the lines between and around them). 1 / 3 means "from line 1 to line 3," which spans across the first two column tracks.

Named grid areas — the most readable Grid pattern#

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

grid-template-areas lets you describe a layout as an actual ASCII picture of the page — genuinely more readable than reasoning about numbered lines for anything beyond a simple grid, and it's self-documenting in the CSS file itself.

Implicit vs. explicit grid#

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* explicit: exactly 3 columns defined */
  grid-auto-rows: 150px; /* implicit: any rows created beyond what's explicitly defined get this size */
  grid-auto-flow: row | column | dense; /* how auto-placed items fill the grid */
}

If you have more items than defined grid cells, Grid creates additional implicit tracks automatically. grid-auto-rows/grid-auto-columns control the size of those auto-generated tracks; grid-auto-flow: dense backfills gaps left by differently-sized items (useful for masonry-like layouts) at the cost of potentially reordering visual placement away from source order.

Subgrid — inheriting the parent's tracks#

.parent {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.child {
  display: grid;
  grid-column: 1 / 4;
  grid-template-columns: subgrid; /* inherits the parent's actual column tracks, not new independent ones */
}

Before subgrid (now broadly supported), a nested grid had no way to align its own tracks with its parent's tracks — two independent grids next to each other could never have their columns line up unless you duplicated the exact same track definitions manually. subgrid solves the classic "cards in a row need their internal elements to align across cards, even though each card is layout-independent" problem properly, covered further in the Modern CSS topic.

Grid vs. Flexbox — deciding#

FlexboxGrid
DimensionsOne axis at a timeTwo axes simultaneously
Best forComponent-internal layout, distributing items in a linePage/section-level layout, precise 2D placement
Content-driven sizingVery naturalPossible but less the default mode
Overlapping itemsAwkwardNatural (items can share grid cells)

A useful heuristic: "do I care about alignment across both rows and columns at once?" — if yes, Grid. If you're just distributing items along one line and wrapping, Flexbox is usually simpler and sufficient. They're frequently combined: Grid for the page skeleton, Flexbox inside individual grid cells/components.


Common Mistakes#

1. Reaching for nested flexbox to fake two-dimensional layout#

/* Awkward: flexbox rows of flexbox columns, fighting to align across rows */
.row { display: flex; }
.row > * { flex: 1; }

If columns need to align consistently across multiple rows (a real grid, not just wrapped items), this is exactly what Grid is for — nested flexbox can approximate it but fights you on alignment the moment content sizes differ between rows.

2. Off-by-one errors with grid line numbers#

/* Wrong: intending to span 2 columns but only spans 1 */
.item { grid-column: 1 / 2; } /* this is ONE column track, not two */
 
/* Right */
.item { grid-column: 1 / 3; } /* or: grid-column: 1 / span 2; */

Grid lines are the boundaries, not the tracks — a common source of off-by-one confusion, especially coming from zero-indexed thinking. span syntax (1 / span 2) avoids having to calculate the end line manually and is usually clearer intent.

3. Forgetting minmax() in repeat(auto-fit/auto-fill, ...), causing items to overflow or never wrap#

/* Wrong: 1fr alone has no minimum, items can shrink to nothing before wrapping ever happens */
grid-template-columns: repeat(auto-fill, 1fr);
 
/* Right */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

Without a minmax() minimum, repeat(auto-fill, 1fr) just creates a single column that never wraps, since 1fr has no defined minimum width for the browser to decide "this doesn't fit, wrap to a new row."

4. Confusing auto-fill and auto-fit and being surprised by extra whitespace or stretched items#

auto-fill keeps empty tracks (visible as gaps if there are fewer items than would fill a row); auto-fit collapses them, letting existing items stretch into the freed space. Test with a small number of items specifically — this is where the difference actually shows up, they're identical when there are enough items to fill every row.

5. Using grid-template-areas with area names that don't form a valid rectangle#

/* Invalid — "header" doesn't form a rectangle */
grid-template-areas:
  "header header"
  "sidebar header";

Every named area must form a complete rectangle across the grid — the browser will reject/ignore an invalid grid-template-areas declaration if the shapes don't tile into rectangles correctly.


Best Practices#

  • Grid for two-dimensional/page-level layout, Flexbox for one-dimensional/component-internal layout — and combine them freely, they're not mutually exclusive.
  • repeat(auto-fill, minmax(Npx, 1fr)) as the default pattern for responsive card/gallery grids without media queries.
  • grid-template-areas for any layout complex enough that numbered-line placement gets hard to read — the ASCII-art readability is worth it.
  • Use span syntax (1 / span 2) over manually calculated end lines to avoid off-by-one errors.
  • Reach for subgrid when nested components need their internal tracks to align with an ancestor grid's tracks, rather than duplicating track definitions.
  • (, ) for complex layouts referenced from multiple places, improving readability over bare numbers.

Further Resources#

  • MDN — CSS Grid Layout
  • CSS-Tricks — A Complete Guide to Grid
  • Grid Garden — interactive game for learning Grid.
  • web.dev — Learn CSS: Grid
  • Rachel Andrew — Grid by Example — patterns from a CSS Grid spec co-editor.
  • MDN — Subgrid

.main { grid-area: main; }
.footer { grid-area: footer; }
Name grid lines
[sidebar-start]
[content-end]