Skip to main content
  • Created:
  • Updated:
  • Author:
    Takeshi Takatsudo

CSS Grid Patterns

The Problem

CSS Grid is the most powerful layout system in CSS, but AI agents often underutilize it or apply it incorrectly. Common mistakes include confusing auto-fill with auto-fit, using fixed column counts instead of responsive patterns, avoiding grid-template-areas when it would dramatically improve readability, and reaching for JavaScript or media queries when minmax() handles responsiveness natively.

The Solution

CSS Grid is a two-dimensional layout system. Use it for page-level layouts, responsive card grids, and any scenario where items need to align across both rows and columns. The combination of auto-fill/auto-fit with minmax() enables responsive layouts without a single media query.

Code Examples

auto-fill vs auto-fit

The difference matters when there are fewer items than the grid can fit.

/* auto-fill: keeps empty tracks, preserving the grid structure */
.grid-fill {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}

/* auto-fit: collapses empty tracks, items stretch to fill space */
.grid-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}

When 3 items are in a container wide enough for 5 columns:

  • auto-fill creates 5 columns, 2 remain empty. Items stay at 200px-ish width.
  • auto-fit collapses the 2 empty columns. Items stretch to fill the full width.

Use auto-fit for card grids, gallery layouts, and most UI patterns where items should expand to use available space.

Use auto-fill when you want to maintain consistent column widths regardless of item count, such as form fields or data entry layouts.

Grid: auto-fill vs auto-fit Comparison

Responsive Card Grid (No Media Queries)

.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
gap: 1.5rem;
}
<div class="card-grid">
<article class="card">Card 1</article>
<article class="card">Card 2</article>
<article class="card">Card 3</article>
<article class="card">Card 4</article>
</div>
Grid: Responsive Card Grid with minmax()

Named Grid Areas

Grid areas make complex layouts readable and maintainable.

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

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

/* Responsive: stack on narrow viewports */
@media (max-width: 768px) {
.page-layout {
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
grid-template-columns: 1fr;
}
}
<div class="page-layout">
<header class="header">Header</header>
<aside class="sidebar">Sidebar</aside>
<main class="main">Main Content</main>
<footer class="footer">Footer</footer>
</div>
Grid: Named Grid Areas Layout

grid-template Shorthand for Complex Layouts

The grid-template shorthand combines grid-template-rows, grid-template-columns, and grid-template-areas in one declaration.

.dashboard {
display: grid;
grid-template:
"nav nav nav" 60px
"side main aside" 1fr
"footer footer footer" 80px
/ 200px 1fr 250px;
min-height: 100vh;
gap: 1rem;
}

Spanning Multiple Rows or Columns

.featured-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 1rem;
}

.featured-item {
grid-column: span 2;
grid-row: span 2;
}

Dense Packing (Filling Gaps)

.masonry-like {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
grid-auto-flow: dense;
gap: 1rem;
}

The dense keyword tells the browser to backfill empty cells with smaller items that appear later in the DOM, creating a tighter layout.

Common AI Mistakes

  • Using auto-fill when auto-fit is intended. Most UI patterns want items to stretch and fill available space (auto-fit). AI agents often pick auto-fill, which leaves empty tracks.
  • Writing minmax(300px, 1fr) without a min() guard. On viewports narrower than 300px, this causes horizontal overflow. Always use minmax(min(100%, 300px), 1fr).
  • Avoiding grid-template-areas. AI agents tend to use row/column numbers for placement, producing unreadable code. Named areas are self-documenting and easier to refactor.
  • Setting explicit column counts instead of using repeat(auto-fit, ...). A fixed grid-template-columns: repeat(3, 1fr) requires media queries to be responsive. auto-fit with minmax() handles this automatically.
  • Using flexbox for a grid of cards. When cards need to align in both rows and columns with consistent sizing, CSS Grid is the correct tool.
  • Forgetting gap and using margin on grid items instead. Grid has built-in gap support. Margins on grid items add space outside the grid tracks, breaking alignment.
  • Not setting min-height: 100vh on full-page grid layouts. Without it, the grid only takes up the height of its content, and areas like the footer will not reach the bottom.

When to Use

CSS Grid is ideal for

  • Two-dimensional layouts (rows and columns simultaneously)
  • Page-level layout with header, sidebar, main, footer
  • Responsive card grids with auto-fit/auto-fill
  • Layouts where items span multiple rows or columns
  • Any layout that benefits from named areas for readability

Use Flexbox instead when

  • You only need a one-dimensional layout (a single row or column)
  • Items have unknown widths and need to distribute space (navigation, toolbars)
  • You want items to wrap but do not need column alignment across rows

Tailwind CSS

Tailwind provides grid utilities with responsive breakpoint prefixes. While CSS Grid's auto-fit/auto-fill with minmax() isn't available as a utility, Tailwind's responsive prefixes (sm:, md:, lg:) offer an explicit breakpoint-based alternative.

Responsive Card Grid

Tailwind: Responsive Grid (resize to see reflow)

Column Spanning

Tailwind: Grid with col-span

References