Fix: CSS Grid Layout Not Working — Items Not Placing or Spanning Correctly
Quick Answer
How to fix CSS Grid issues — implicit vs explicit grid, grid-template-areas, auto-placement, subgrid, alignment, and common mistakes with grid-column and grid-row.
The Problem
CSS Grid items don’t position where expected:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.item {
grid-column: 2 / 4; /* Supposed to span columns 2 and 3 */
}
/* Item doesn't span correctly — or disappears entirely */Or a named area layout doesn’t render:
.container {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; } /* Has no effect */Or items overflow the grid or stack instead of spreading across columns.
Why This Happens
CSS Grid has a large surface area and several non-obvious behaviors:
display: gridon the parent, not the children — a common mistake is applyingdisplay: gridto the items rather than the container.- Implicit vs explicit grid — columns/rows you define are “explicit.” Items that don’t fit create “implicit” tracks with auto sizing, which may not match your intent.
- Line numbering starts at 1 —
grid-column: 1 / 3spans from line 1 to line 3 (covering 2 columns). Negative numbers count from the end:-1is the last line. grid-template-areasrequires every cell — each row in the template must have the same number of cells, and every area name must form a rectangle. A.represents an empty cell.grid-areaname must match exactly —grid-area: headerrequires"header"ingrid-template-areas. Case-sensitive.gapvsgrid-gap—grid-gapis deprecated. Usegap. Some older browsers need the prefix.
Fix 1: Verify display: grid Is on the Container
display: grid turns an element into a grid container. Its direct children become grid items:
/* WRONG — grid on the item, not the container */
.item {
display: grid;
grid-column: 1 / 3;
}
/* CORRECT — grid on the container */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.item {
grid-column: 1 / 3; /* Now this works */
}Grid only affects direct children:
<div class="container"> <!-- display: grid here -->
<div class="item"> <!-- Direct child = grid item ✓ -->
<span>Not a grid item</span> <!-- Grandchild = NOT a grid item -->
</div>
</div>Fix 2: Understand Grid Line Numbers
Grid lines are numbered starting at 1. A 3-column grid has 4 vertical lines:
1 2 3 4
| A | B | C |
grid-column: 1 / 2 → column A only
grid-column: 1 / 3 → columns A and B
grid-column: 2 / 4 → columns B and C
grid-column: 1 / -1 → all columns (1 to last line)
grid-column: span 2 → span 2 columns from current position.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
/* Span from column 2 to end */
.item {
grid-column: 2 / -1; /* Line 2 to last line */
}
/* Span 2 columns starting from wherever auto-placed */
.wide-item {
grid-column: span 2;
}
/* Place at specific position */
.positioned {
grid-column: 2; /* Shorthand for 2 / 3 */
grid-row: 1 / 3; /* Span 2 rows */
}Fix 3: Fix grid-template-areas
Named areas must form complete rectangles, and every row needs the same cell count:
/* WRONG — uneven row lengths */
.container {
display: grid;
grid-template-areas:
"header header header"
"sidebar main" /* Only 2 cells — error */
"footer"; /* Only 1 cell — error */
}
/* WRONG — area doesn't form a rectangle */
.container {
display: grid;
grid-template-areas:
"header sidebar"
"main sidebar"
"footer header"; /* 'header' appears in two non-contiguous rows — invalid */
}
/* CORRECT — rectangular areas, equal row lengths */
.container {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }Use . for empty cells:
.container {
grid-template-areas:
"logo nav nav"
". content content"
"footer footer footer";
}
/* The dot '.' leaves that cell empty */Fix 4: Fix Implicit Grid Behavior
When items don’t fit in the explicit grid, they’re placed in the implicit grid using auto-sizing:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Only defines columns — rows are implicit */
}
/* Implicit rows default to auto (content height) */
/* To control implicit row size: */
.container {
grid-auto-rows: 200px; /* Fixed height */
grid-auto-rows: minmax(100px, auto); /* Min 100px, grows with content */
}
/* Auto-placement direction */
.container {
grid-auto-flow: row; /* Default: fill rows left to right */
grid-auto-flow: column; /* Fill columns top to bottom */
grid-auto-flow: row dense; /* Fill gaps when items span multiple cells */
}dense packing to fill gaps:
/* Without dense: a 2-column-wide item leaves gaps before smaller items */
/* With dense: smaller items backfill gaps */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-flow: row dense;
}
.wide { grid-column: span 2; }
.tall { grid-row: span 2; }Fix 5: Alignment and Stretching
Grid items stretch to fill their cell by default. Override with alignment properties:
/* Container-level alignment (affects ALL items) */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Align items along the row axis (horizontal) */
justify-items: stretch; /* default */
justify-items: start;
justify-items: end;
justify-items: center;
/* Align items along the column axis (vertical) */
align-items: stretch; /* default */
align-items: start;
align-items: end;
align-items: center;
/* Shorthand */
place-items: center; /* align-items + justify-items */
place-items: start end; /* vertical horizontal */
}
/* Align the grid tracks within the container */
.container {
width: 800px;
grid-template-columns: repeat(3, 200px); /* Total: 600px < 800px */
justify-content: start; /* default — tracks at start */
justify-content: center; /* tracks centered */
justify-content: space-between;
justify-content: space-around;
}
/* Per-item alignment override */
.item {
justify-self: center; /* Override justify-items for this item */
align-self: end; /* Override align-items for this item */
}Fix 6: Use minmax() and fr Units Correctly
fr units and minmax() enable flexible layouts without overflow:
/* fr unit — fraction of remaining space */
.container {
display: grid;
/* 3 equal columns */
grid-template-columns: repeat(3, 1fr);
/* 1fr min 200px — never smaller than 200px */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* Auto-fill: as many columns as fit, min 200px each */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* Auto-fit: same as auto-fill but collapses empty tracks */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}auto-fill vs auto-fit:
/* auto-fill — creates empty columns to fill the row */
/* auto-fit — collapses empty columns, stretches existing items */
/* For responsive card grids, auto-fit is usually better: */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
/* Cards fill the available width at any viewport size */Avoid fr with content overflow:
/* PROBLEM: fr doesn't prevent overflow from long content */
.container {
grid-template-columns: 1fr 1fr;
}
.item {
/* Long word or code block can overflow a 1fr column */
}
/* FIX: use minmax with min-content */
.container {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
/* minmax(0, 1fr) allows column to shrink below content size */
}Fix 7: Subgrid for Nested Alignment
Subgrid lets nested grids align to the parent grid’s tracks:
/* Parent grid */
.layout {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
/* Card that spans 2 columns and uses parent's column tracks */
.card {
grid-column: span 2;
display: grid;
grid-template-columns: subgrid; /* Uses parent's 2 remaining column tracks */
}
/* Card content aligns to parent grid lines */
.card-image {
grid-column: 1; /* First track of parent grid under the card */
}
.card-text {
grid-column: 2; /* Second track */
}Note:
subgridis supported in all modern browsers as of 2023. Check if your target browsers support it before using.
Still Not Working?
height: 100% on grid items — grid items don’t automatically fill the container’s height unless align-items: stretch (the default) is set on the container. If items have explicit heights set, they won’t stretch.
Overflow from non-grid children — if a non-grid element (e.g., an absolutely positioned child) causes overflow, it won’t affect grid layout but may visually overflow the container. Use overflow: hidden on the container or position: relative on a wrapper.
CSS Grid in Firefox vs Chrome — minor rendering differences exist between browsers. Firefox DevTools has the best CSS Grid inspector — use it to visualize grid lines, areas, and gaps.
grid shorthand is complex — the grid shorthand property combines grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, and grid-auto-flow. Avoid the shorthand until you’re comfortable with each individual property.
For related CSS issues, see Fix: CSS Flexbox Not Working and Fix: CSS Animation Not Working.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: CSS Scroll Behavior Not Working — smooth scroll, scroll-snap, or scroll-margin Ignored
How to fix CSS scroll issues — scroll-behavior: smooth not working, scroll-snap alignment problems, overflow container conflicts, scroll-margin for fixed headers, and browser compatibility.
Fix: Mantine Not Working — Styles Not Loading, Theme Not Applying, or Components Broken After Upgrade
How to fix Mantine UI issues — MantineProvider setup, PostCSS configuration, theme customization, dark mode, form validation with useForm, and Next.js App Router integration.
Fix: View Transitions API Not Working — No Animation Between Pages, Cross-Document Transitions Failing, or Fallback Missing
How to fix View Transitions API issues — same-document transitions, cross-document MPA transitions, view-transition-name CSS, Next.js and Astro integration, custom animations, and browser support.
Fix: Panda CSS Not Working — Styles Not Applying, Tokens Not Resolving, or Build Errors
How to fix Panda CSS issues — PostCSS setup, panda.config.ts token system, recipe and pattern definitions, conditional styles, responsive design, and integration with Next.js and Vite.