Fix: CSS Grid Not Working (display: grid Has No Effect)
Quick Answer
How to fix CSS Grid not working — grid-template-columns has no effect, grid items not placing correctly, implicit vs explicit grid confusion, and common grid layout debugging techniques.
The Error
You add display: grid and grid-template-columns to a container but the layout does not change. Items still stack vertically, columns are not created, or items are placed in unexpected positions. No error message appears — the grid just does not behave as expected.
Common symptoms:
grid-template-columns: repeat(3, 1fr)defined but items still appear in one column.grid-column: span 2on an item has no effect.- Items overflow the grid container instead of wrapping.
align-itemsandjustify-itemsdo nothing.- The grid works on desktop but breaks on mobile.
gapbetween grid items is not visible.- A grid item stretches to unexpected dimensions.
Why This Happens
CSS Grid applies rules to the grid container (display: grid) and grid items (direct children). Problems arise when:
display: gridis on the wrong element — grandchildren are not grid items.- The container has no width or height — grid tracks cannot be created without dimensions.
- Implicit vs explicit grid confusion — items placed outside defined columns/rows create implicit tracks with different sizing.
grid-template-columnswithout units —repeat(3, 1fr)requires free space; if the container has no width,1fr= 0.- Conflicting properties —
widthon a grid item overridesfrsizing;position: absolutetakes items out of grid flow. - Browser support issues — older syntax (
-ms-grid) differs from modern Grid. grid-areaname typos — named template areas silently fail if names do not match.
Fix 1: Verify display: grid Is on the Container
display: grid turns an element into a grid container. Its direct children become grid items. Grandchildren are not grid items and are unaffected by the container’s grid rules.
Broken — grid on wrong element:
/* You want a 3-column layout for the cards */
.card-grid {
/* display: grid missing here */
}
.card {
display: grid; /* Makes each card a grid internally, not what you want */
grid-template-columns: repeat(3, 1fr); /* Has no layout effect on siblings */
}Fixed:
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.card {
/* No grid needed here unless the card itself has a grid layout */
}Verify with DevTools: In Chrome or Firefox DevTools, click the grid badge next to the container element in the Elements panel. The Grid inspector overlays the grid lines on the page — if no overlay appears, display: grid is not active on that element.
Fix 2: Fix fr Units Requiring a Defined Container Width
1fr means “one fraction of the available free space.” If the container has no width, there is no free space, and 1fr equals zero.
Broken — container width not defined:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Container has no width — inherits from parent which may be 0 */
}Fixed — ensure the container has a width:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
width: 100%; /* Or a specific width */
max-width: 1200px;
margin: 0 auto;
}For column grids, the container needs a width. For row grids (grid-template-rows), it needs a height. A block-level element (div) naturally fills its parent’s width, so this is usually only an issue when the parent itself has no width.
Pro Tip: Use
minmax(0, 1fr)instead of1frfor grid columns that contain text or other potentially large content.1frhas an implicit minimum ofauto(content size), which can cause overflow.minmax(0, 1fr)sets the minimum to 0, allowing the column to shrink below its content size.
Fix 3: Fix Grid Item Placement Issues
Grid items are placed automatically by default (left-to-right, row by row). Explicit placement with grid-column and grid-row overrides this.
Broken — item placed outside the explicit grid:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 columns defined */
}
.item {
grid-column: 4; /* Column 4 does not exist explicitly */
/* Creates an implicit column — may have auto sizing (often 0 or content-width) */
}Fixed — use valid column numbers:
.item {
grid-column: 1 / 3; /* Span from line 1 to line 3 (columns 1 and 2) */
/* Or: */
grid-column: span 2; /* Span 2 columns from current position */
}Grid line numbers start at 1, not 0. A 3-column grid has lines 1, 2, 3, 4 — four lines for three columns. Negative numbers count from the end: -1 is the last line.
/* Span the full width of a 3-column grid */
.full-width {
grid-column: 1 / -1; /* From first line to last line */
}Fix 4: Fix Implicit Grid Track Sizing
When grid items are placed outside the explicitly defined grid (more rows than grid-template-rows defines, or columns beyond grid-template-columns), they go into the implicit grid. Implicit tracks default to auto sizing, which is often not what you want.
Control implicit track size:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Implicit rows are auto-sized by default */
grid-auto-rows: 200px; /* All implicit rows are 200px */
/* Or: */
grid-auto-rows: minmax(100px, auto); /* Min 100px, grows with content */
}Control implicit column direction:
.grid {
display: grid;
grid-auto-flow: column; /* Items flow into columns instead of rows */
grid-auto-columns: 200px;
}Fix 5: Fix Named Template Areas
grid-template-areas lets you name regions and assign items to them with grid-area. Name mismatches fail silently.
Broken — name mismatch:
.grid {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.nav {
grid-area: sidebar; /* Correct */
}
.content {
grid-area: content; /* Wrong — should be "main" */
/* Item is placed in the implicit grid instead */
}Fixed — names must match exactly:
.content {
grid-area: main; /* Matches the template area name */
}Rules for named areas:
- Names in
grid-template-areasmust be valid CSS identifiers (no spaces, no special characters except-and_). - Each row must have the same number of columns.
- A
.represents an empty cell. - An area must be rectangular — L-shapes are not allowed.
grid-template-areas:
"header header header"
"sidebar main main"
". footer footer"; /* . = empty cell */Fix 6: Fix Grid with Absolutely Positioned Items
Absolutely positioned elements are taken out of the grid flow. They do not participate in grid auto-placement, but they can be positioned using grid line numbers as coordinates:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
position: relative; /* Required for absolute children */
}
.overlay {
position: absolute; /* Out of grid flow */
grid-column: 2 / 3; /* This has NO effect on absolutely positioned items */
top: 0;
left: 0;
width: 100%;
}To position an absolutely positioned item within the grid, use top/left/right/bottom with percentage values, or use inset — not grid properties.
If you want an element to span grid areas while remaining in the flow, use grid-column and grid-row without position: absolute.
Fix 7: Fix CSS Grid on Specific Elements
Grid on <table>, <tr>, <td>. Table elements have forced display types. Adding display: grid to a <table> may work in some browsers but produces inconsistent results. Use a <div> wrapper instead.
Grid on <button> or <input>. These elements may have browser-specific default styles that interfere with grid. Explicitly set display: grid and verify computed styles.
Grid children that are inline elements. display: grid on the container turns direct children into block-level boxes regardless of their original display type — so <span> and <a> children behave like blocks inside a grid. This is usually the desired behavior.
Tailwind CSS: If you are using Tailwind and grid classes are not applying, see Fix: Tailwind CSS classes not applying. For z-index stacking issues with overlapping grid items, see Fix: CSS z-index not working.
For Flexbox-specific issues, see Fix: CSS Flexbox not working.
Fix 8: Fix Responsive Grid Layouts
Use auto-fill or auto-fit for responsive columns without media queries:
.grid {
display: grid;
/* auto-fill: creates as many columns as fit, keeps empty columns */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* auto-fit: creates as many columns as fit, collapses empty columns */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}minmax(200px, 1fr) means each column is at least 200px wide and expands to fill available space. On a 600px container: 3 columns. On a 400px container: 2 columns. On a 200px container: 1 column. No media queries needed.
Difference between auto-fill and auto-fit:
auto-fill: creates empty columns to fill the row (items may not stretch to full width on sparse rows).auto-fit: collapses empty columns (items stretch to fill the full row width on sparse rows).
Debugging CSS Grid
Use the browser Grid inspector. In Chrome DevTools, click the grid badge in the Elements panel. In Firefox, click the grid indicator. Both show grid line numbers, track sizes, and named areas overlaid on the page.
Add temporary borders to see grid boundaries:
.grid {
border: 2px solid red;
}
.grid > * {
border: 1px solid blue;
background: rgba(0, 0, 255, 0.05);
}Check computed styles. The Computed panel in DevTools shows the final resolved value of grid-template-columns and grid-template-rows — including the pixel values that fr units resolved to. If columns show as 0px, the container has no available width.
Simplify first. Remove all other styling and test with just display: grid and grid-template-columns. Add properties back one at a time until the layout breaks.
Still Not Working?
Check for overflow: hidden on the container. This can clip grid items that extend outside the container, making it appear the grid is not working when items are simply hidden.
Check for min-height: 0 on grid rows. Similar to Flexbox, grid tracks have a minimum size of auto by default, meaning they will not shrink below their content size. If a grid row is not shrinking, add min-height: 0 to the row’s items or the container.
Check browser support for specific features. subgrid (allowing nested grids to align to the parent grid) was added in Chrome 117, Firefox 71, Safari 16. masonry layout is still experimental. Check MDN for compatibility.
Check for gap browser support. gap (formerly grid-gap) for Grid is supported in all modern browsers since 2017. If gap is not working, you may be on an old browser that requires the grid-gap prefix.
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 Custom Properties (Variables) Not Working or Not Updating
How to fix CSS custom properties not applying — wrong scope, missing fallback values, JavaScript not setting variables on the right element, and how CSS variables interact with media queries and Shadow DOM.
Fix: CSS Animation Not Working (@keyframes Has No Effect)
How to fix CSS animations not working — @keyframes not applying, animation paused, transform conflicts, reduced motion settings, and common animation property mistakes.
Fix: CSS position: sticky Not Working
How to fix CSS position sticky not working — element scrolls away instead of sticking, caused by overflow hidden on a parent, missing top value, wrong stacking context, or incorrect height on the container.
Fix: CSS Flexbox Not Working (display: flex Has No Effect)
How to fix CSS Flexbox not working — why display flex has no effect, flex children not aligning, flex-grow not stretching, and how to debug common Flexbox layout issues.