CSS Grid in Practice: From repeat() to grid-template-areas
CSS Grid in Practice: From repeat() to grid-template-areas#
I was refactoring an admin dashboard recently. The layout seemed simple at first: fixed sidebar on the left, main content on the right. But the main area needed a stats section with 3 auto-fitting columns above a data table. After nesting Flexbox containers three levels deep, I realized—this is Grid’s home turf.
Grid vs Flexbox: The Key Difference#
Flexbox is one-dimensional. Grid is two-dimensional.
/* Flexbox: controls one direction at a time */
.container {
display: flex;
flex-direction: row; /* or column */
}
/* Grid: controls rows AND columns simultaneously */
.container {
display: grid;
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: 60px 1fr;
}
Grid properties fall into two categories:
- Container properties:
grid-template-columns,grid-template-rows,gap,justify-items,align-items - Item properties:
grid-column,grid-row,grid-area
The repeat() Function: Stop Writing Repetitive Values#
repeat() is Grid’s most used function:
/* 3 equal-width columns */
.container {
grid-template-columns: repeat(3, 1fr);
}
/* Equivalent to */
.container {
grid-template-columns: 1fr 1fr 1fr;
}
/* Mixed usage */
.container {
grid-template-columns: 200px repeat(3, 1fr) 100px;
/* Fixed 200px left, 3 auto columns middle, fixed 100px right */
}
1fr is a Grid-specific unit meaning “one fraction of available space.” In a 1000px container, repeat(3, 1fr) gives each column 333.33px.
minmax(): Responsive Boundaries#
The pain of responsive layouts: content gets squeezed on small screens, stretched on large ones. minmax() sets both minimum and maximum:
.container {
/* Each column: minimum 200px, maximum 1fr */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
auto-fit calculates column count based on container width. A 1000px container fits 5 columns (1000 ÷ 200 = 5). A 600px container fits only 3.
Perfect for card layouts:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
grid-template-areas: Semantic Layout#
Grid’s most powerful feature is grid-template-areas. You “draw” the layout with strings:
.container {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
}
.sidebar { grid-area: sidebar; }
.header { grid-area: header; }
.main { grid-area: main; }
.footer { grid-area: footer; }
Benefits:
- Readable: Layout structure is obvious at a glance
- Easy to modify: Change strings to change layout
- Responsive-friendly: Rewrite
grid-template-areasin media queries
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"header"
"main"
"footer";
/* Hide sidebar on mobile */
}
.sidebar { display: none; }
}
The gap Property: Spacing Made Simple#
Grid’s gap is much cleaner than Flexbox’s margin approach:
.container {
gap: 20px; /* Both row and column gap: 20px */
/* Or set separately */
row-gap: 16px;
column-gap: 24px;
/* Shorthand */
gap: 16px 24px; /* Row gap 16px, column gap 24px */
}
justify-items and align-items#
These control how items align within their cells:
.container {
justify-items: stretch; /* Horizontal stretch (default) */
align-items: stretch; /* Vertical stretch (default) */
/* Other values: start | center | end */
}
Common use case: centering buttons in cells:
.button-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
justify-items: center; /* Buttons centered horizontally */
gap: 12px;
}
.button-grid button {
width: 120px; /* Fixed button width */
}
Real-World Example: Admin Dashboard#
Back to my original requirement, here’s the Grid implementation:
.admin-layout {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 60px 1fr;
grid-template-areas:
"sidebar header"
"sidebar main";
height: 100vh;
}
.sidebar { grid-area: sidebar; }
.header { grid-area: header; }
.main {
grid-area: main;
display: grid;
grid-template-rows: auto 1fr;
gap: 24px;
padding: 24px;
}
/* Stats cards */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
/* Data table */
.table-container {
overflow: auto;
}
Clean structure, no nesting hell.
Debugging Grid#
Chrome DevTools has built-in Grid visualization:
- Open DevTools, select a Grid container
- Click the
gridbadge in the Elements panel - Check “Show grid lines” and “Show track sizes”
You’ll see grid lines and dimensions visually, making layout issues easy to spot.
Browser Support#
Grid has been supported by all major browsers since 2017. IE11 supports a prefixed version with some behavioral differences. For IE11 support, use Autoprefixer:
/* Autoprefixer output */
.container {
display: -ms-grid;
display: grid;
-ms-grid-columns: 200px 1fr;
grid-template-columns: 200px 1fr;
}
Online Tool#
I built a Grid Layout Generator for quick prototyping: Grid Generator
Features:
- Visual row/column adjustment
- Live preview
- One-click CSS copy
- justify-items and align-items controls
Related: Flexbox Generator | CSS Gradient Generator