Home/Blog/Common CSS Grid Mistakes and How to Fix Them
🎨
css grid not workingcss grid mistakesgrid-template-columns not working

Common CSS Grid Mistakes and How to Fix Them

The most common CSS Grid mistakes developers make — forgetting display: grid, sizing unit confusion, overflow bugs, typo'd grid-template-areas, and more — each with broken and fixed code.

July 13, 20267 min readby ToolNinja

Why CSS Grid Feels Harder Than It Should Be

CSS Grid is the most powerful layout system in CSS, but it's also the one where small mistakes produce confusing, silent failures — no console error, no red squiggly line, just a layout that doesn't look right. Unlike JavaScript, a broken grid property doesn't throw; it just gets ignored or falls back to a default.

Here are the seven mistakes that account for almost every "why isn't my grid working" question, each with the broken code, why it fails, and the fix.


1. Forgetting display: grid on the Parent

This is, by far, the most common mistake — and the easiest to miss because everything else about your CSS can be correct.

Broken:

.container {
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
}

Why it fails: grid-template-columns, gap, grid-template-areas — none of these do anything unless the element is actually a grid container. Without display: grid, the browser treats .container as a normal block element and every grid property is simply invalid-and-ignored on that element.

Fixed:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
}

2. Confusing fr, px, and % in grid-template-columns

Broken:

.container {
  display: grid;
  grid-template-columns: 100% 100% 100%;
}

Why it fails: Percentages in grid-template-columns are relative to the size of the grid container itself — not divided evenly among tracks. Three columns of 100% each ask for 300% of the container's width, which the browser can't satisfy, so columns overflow or collapse unpredictably.

Fixed:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

fr (a "fraction unit") divides the remaining free space after fixed-size tracks are subtracted — which is what people actually mean when they reach for a percentage. Mix units freely: grid-template-columns: 200px 1fr 2fr gives you a fixed 200px sidebar, then splits the rest 1:2 between the remaining two columns.


3. Grid Items Overflowing Because of min-width: auto

Broken:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.card {
  overflow: hidden;
}

A card with a long unbroken URL or a wide <pre> block still blows out of its column, even with overflow: hidden set.

Why it fails: Grid (and Flex) items have an implicit min-width: auto and min-height: auto. That means the browser refuses to shrink the item below its content's intrinsic minimum size — a long word or a wide image — no matter how narrow the track is. overflow: hidden only clips visually; it doesn't change the sizing calculation that caused the overflow in the first place.

Fixed:

.card {
  min-width: 0;
  overflow: hidden;
}

Setting min-width: 0 (and min-height: 0 for row overflow) tells the browser it's allowed to shrink the item below its content's natural size, letting overflow and text-overflow: ellipsis actually do their job.


4. grid-gap vs gap — Old vs New Syntax

Broken (not actually broken, just outdated):

.container {
  display: grid;
  grid-gap: 16px;
  grid-column-gap: 8px;
}

Why it's a problem: grid-gap, grid-column-gap, and grid-row-gap were the original Grid-specific property names. They still work in every modern browser via an alias, but the spec renamed them to the unprefixed gap, column-gap, and row-gap — which now also work in Flexbox, not just Grid. Mixing both forms in one codebase is a common source of "wait, which one actually applies?" confusion, and some linters flag the old names as deprecated.

Fixed:

.container {
  display: grid;
  gap: 16px;
  column-gap: 8px;
}

Use the unprefixed gap shorthand (gap: row column) everywhere — it's supported in every browser still receiving updates and works identically in Grid and Flexbox.


5. Typos in grid-template-areas (Silent Failure)

Broken:

.container {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main"
    "sidebar footer";
}
.header  { grid-area: header; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }
.sidebar { grid-area: sidebar; }
.nav     { grid-area: nagivation; } /* typo */

Why it fails: grid-template-areas is pure string matching. There's no validation step — a misspelled area name (nagivation instead of navigation), a row with a different number of cells than the others, or an area referenced in grid-area that never appears in the template just gets silently ignored. The element falls back to being auto-placed, which often looks like it "disappeared" from where you expected it.

Fixed: Keep every area name consistent between the grid-template-areas string and each element's grid-area declaration, and make sure every row in the template string has the same number of quoted cells:

.nav { grid-area: navigation; }

Tip: name every area only once in the CSS, right next to grid-template-areas, as a comment — it makes mismatches easy to spot on review.


6. Implicit vs Explicit Grid Rows Causing Unexpected Layout

Broken:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 100px 100px;
}

If you render 9 items into this grid, the 7th, 8th, and 9th land in rows sized by the browser's default auto height, not the fixed 100px you defined — often producing a visually inconsistent grid where the last row is a different height than the rest.

Why it happens: grid-template-rows only defines the explicit grid — the rows you named up front. Any content that doesn't fit inside that explicit grid spills into the implicit grid, which by default sizes rows to auto (fit-content).

Fixed:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
}

grid-auto-rows sets the size for every row the browser creates implicitly — so overflow rows stay consistent with the rest of the grid. Use grid-template-rows for a fixed, known number of rows; use grid-auto-rows when the row count depends on dynamic content.


7. Nested Grids Not Inheriting Parent Sizing

Broken:

.outer {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.inner {
  display: grid;
  grid-template-columns: subgrid; /* used without checking support */
}

Or, more commonly, developers expect an .inner grid item to automatically line up its own columns with the outer grid's columns — and it doesn't, because a nested grid creates a completely new, independent formatting context by default.

Why it happens: A grid item that is itself display: grid starts a brand-new grid from scratch. Its rows and columns have no relationship to the parent grid's tracks unless you explicitly opt in.

Fixed: Use subgrid (supported in all current evergreen browsers as of 2026) to have a nested grid inherit its parent's track sizing directly:

.inner {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / 5;
}

If you need to support an older engine without subgrid, the fallback is to manually re-declare matching fr values on the inner grid, though this breaks the moment the outer grid's tracks change.


Quick Reference

MistakeSymptomFix
No display: gridGrid properties do nothingAdd display: grid to the parent
% instead of frColumns overflow or collapseUse fr units for proportional tracks
Content overflows its trackoverflow: hidden doesn't helpSet min-width: 0 / min-height: 0 on the item
Mixed grid-gap / gapInconsistent, deprecated syntaxStandardize on gap / column-gap / row-gap
Typo in grid-template-areasItem vanishes or misplacesMatch area names exactly, equal cells per row
No grid-auto-rowsOverflow rows are inconsistent sizeSet grid-auto-rows for implicit rows
Nested grid ignores parent tracksInner columns don't line upUse subgrid or manually match fr values

Build Your Layout Visually

ToolNinja doesn't have a dedicated Grid Builder yet, but you can prototype the visual side of a layout right now with the CSS Gradient Generator for backgrounds and panel treatments, and CSS Animations for copy-paste transition and hover effects to drop into your grid items. A dedicated visual Grid Builder is on our radar as a future tool — if that's something you'd use, it's a good sign CSS Grid tooling is worth investing in further.

Share:𝕏 Twitterin LinkedIn

Frequently Asked Questions

Why isn't my CSS Grid working at all?

The most common cause is a missing display: grid (or display: inline-grid) on the parent container. Without it, grid-template-columns, gap, and every other grid property are silently ignored and the children lay out as normal block elements.

What's the difference between CSS Grid and Flexbox?

Flexbox is one-dimensional — it lays items out along a single row or column and excels at distributing space between them. Grid is two-dimensional — it lets you define rows and columns together and place items precisely in a layout. Use Flexbox for a nav bar or a row of buttons; use Grid for a page layout or a card gallery with rows and columns.

Why does my grid item overflow its column?

Grid items have a default min-width (and min-height) of auto, which means they refuse to shrink smaller than their content — a long unbroken string or a wide image will blow out the column. Set min-width: 0 on the item to let it shrink to fit the track.

Why did my grid-template-areas layout silently break?

grid-template-areas has no error reporting — a typo in an area name, a missing cell, or unequal row lengths just makes the browser ignore the property or place items in unexpected default positions. Double-check every named area appears in both the CSS grid-area declarations and the template-areas string, with matching quotes per row.

🥷 ToolNinja