Activating CSS Grid
.container { display: grid; }
/* or: */
.container { display: inline-grid; } /* grid that flows inline */
Direct children of a grid container automatically become grid items. Without defining columns/rows, items stack vertically in a single column (like block display).
grid-template-columns & grid-template-rows
Define the grid's track structure. Each value in the list defines one column (or row) and its size.
/* 3 equal columns of 200px each */
grid-template-columns: 200px 200px 200px;
/* 3 columns with different sizes */
grid-template-columns: 260px 1fr 1fr; /* sidebar + 2 equal mains */
/* 2 rows of specific heights */
grid-template-rows: 64px 1fr; /* fixed header + flexible content */
The fr Unit – Fractional Space
fr (fraction) represents a fraction of the available free space in the grid container. It's the most important CSS Grid unit.
/* 3 equal columns — each gets 1/3 of available width */
grid-template-columns: 1fr 1fr 1fr;
/* Unequal — first gets 1/4, second 3/4 */
grid-template-columns: 1fr 3fr;
/* Mix px and fr — px columns are sized first, fr gets the rest */
grid-template-columns: 260px 1fr; /* fixed sidebar + flexible main */
grid-template-columns: 260px 1fr 300px; /* sidebar + main + ads */
repeat() – Shorthand for Repeated Tracks
/* Verbose */
grid-template-columns: 1fr 1fr 1fr 1fr;
/* Same with repeat(count, size) */
grid-template-columns: repeat(4, 1fr);
/* Repeat a pattern */
grid-template-columns: repeat(3, 1fr 2fr);
/* = 1fr 2fr 1fr 2fr 1fr 2fr */
/* auto-fill — create as many columns as fit */
grid-template-columns: repeat(auto-fill, 200px);
/* auto-fit — same but collapses empty tracks */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
minmax() – Flexible Track Sizing
minmax(min, max) defines a track that is at least min wide and at most max wide.
/* Column that's at least 200px but can grow to fill space */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* The responsive card grid — the most used Grid pattern */
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
/* Creates as many 280px+ columns as fit. When space is tight:
fewer columns. When space is wide: more columns. Zero media queries! */
gap – Spacing Between Tracks
gap: 24px; /* equal row and column gap */
gap: 16px 24px; /* row-gap: 16px, column-gap: 24px */
row-gap: 16px;
column-gap: 24px;
Placing Items – grid-column & grid-row
Grid items can be placed on specific lines. Grid lines are numbered from 1 (or -1 from the end).
/* grid-column: start / end */
.wide-item {
grid-column: 1 / 3; /* spans from line 1 to line 3 (2 columns) */
}
/* span keyword — span N tracks */
.wide-item {
grid-column: span 2; /* spans 2 columns from wherever it auto-places */
}
/* grid-row: start / end */
.tall-item {
grid-row: 1 / 3; /* spans 2 rows */
}
/* From the end — -1 = last line */
.full-width {
grid-column: 1 / -1; /* spans all columns regardless of how many */
}
Named Grid Areas
The most readable way to define complex layouts. Name areas in the template, then assign items to areas.
.page {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
grid-template-columns: 260px 1fr 1fr;
grid-template-rows: 64px 1fr 60px;
min-height: 100vh;
gap: 0;
}
.site-header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main-content { grid-area: main; }
.site-footer { grid-area: footer; }
/* Use . (dot) for an empty cell */
grid-template-areas:
"header header"
"sidebar main"
". footer";
Alignment in Grid
/* Align ALL items within their cells */
align-items: start | end | center | stretch; /* cross axis (vertical) */
justify-items: start | end | center | stretch; /* main axis (horizontal) */
place-items: center; /* shorthand: align + justify */
/* Align individual item within its cell */
align-self: center; /* vertical */
justify-self: center; /* horizontal */
place-self: center; /* shorthand */
/* Align entire grid inside container (when grid is smaller than container) */
align-content: start | end | center | space-between | space-around;
justify-content: center;
Real-World Grid Patterns
/* 1. Responsive card grid — no media queries needed */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
/* 2. Full-page layout */
.app {
display: grid;
grid-template-rows: 60px 1fr 48px;
grid-template-areas: "header" "main" "footer";
min-height: 100vh;
}
/* 3. Image masonry-style gallery */
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px;
gap: 12px;
}
.gallery .featured {
grid-column: span 2;
grid-row: span 2;
}
/* 4. 12-column layout (like Bootstrap) */
.grid-12 {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 16px;
}
.col-6 { grid-column: span 6; } /* half width */
.col-4 { grid-column: span 4; } /* one third */
.col-3 { grid-column: span 3; } /* one quarter */
/* 5. CSS Grid centering (alternative to flexbox) */
.center {
display: grid;
place-items: center;
}
Grid or Flexbox? And the auto-fit vs auto-fill Trap
They're not competitors — they solve different shapes of problem.
| Use Flexbox when… | Use Grid when… |
|---|---|
| content flows in one direction (a row or a column) | you place items in two dimensions (rows and columns) |
| sizes depend on content (nav bars, tag lists) | you want a defined structure the content fills |
| you're aligning items within a line | you're building a page/gallery layout |
The classic responsive gallery needs no media queries:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
auto-fit vs auto-fill
They look identical until the row isn't full. auto-fill keeps empty phantom columns, so your items stay their min width. auto-fit collapses empty tracks, letting the existing items stretch to fill the row. For most galleries you want auto-fit.
🏋️ Practical Exercise
- Make a container
display: grid. - Define columns with
grid-template-columns. - Space cells with
gap. - Use
frunits for flexible columns. - Span a cell across two columns with
grid-column.
🔥 Challenge Exercise
Build a responsive photo gallery using repeat(auto-fit, minmax(200px, 1fr)) so columns wrap automatically, and make one featured item span two columns. Explain how Grid differs from Flexbox and when to choose each.
📋 Summary
- display: grid — activates Grid on the container.
- grid-template-columns / rows — define the track structure.
- fr — fractional unit.
1fr= equal share of available space. - repeat(count, size) — shorthand for repeated tracks.
- minmax(min, max) — flexible track that stays between min and max.
- repeat(auto-fit, minmax(280px, 1fr)) — the responsive card grid pattern.
- grid-column/row: start / end — place items on specific lines.
span Nto span N tracks. - grid-column: 1 / -1 — always spans all columns.
- grid-template-areas + grid-area — named layout regions, most readable approach.
- gap — spacing between rows and columns.
- place-items: center — center all items in cells.
Interview Questions
- What is CSS Grid used for?
- What is the difference between Grid and Flexbox?
- What does the
frunit represent? - How does
repeat(auto-fit, minmax())create responsive columns? - How do you make an item span multiple columns or rows?
Related Topics
FAQ
Both create as many columns as fit the container. The difference appears when there are fewer items than columns: auto-fill creates empty tracks (the grid has empty columns), auto-fit collapses empty tracks (the existing items stretch to fill the space). For most card grids you want auto-fit so items expand when there are fewer of them. Use auto-fill when you want a fixed grid structure regardless of item count.
Grid excels at two-dimensional layouts — when you need to control both rows and columns simultaneously, or when the parent controls the layout (known size containers). Flexbox excels at one-dimensional layouts — rows of items, vertical stacking, when the content controls the size (unknown sizes). In practice: Grid for page-level layout, Grid for galleries and card grids, Flexbox for navigation bars, button groups, form rows, and component internals. They're complementary — use both in the same project.
The magic one-liner: grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)). This creates as many columns as fit, where each is at least 280px wide and at most 1fr (fills available space). On a narrow viewport: 1 column. On a medium viewport: 2 columns. On a wide viewport: 3+ columns. No media queries needed. Adjust 280px to suit your content — it's the breakpoint where columns collapse.
grid-area has two uses: (1) Assign a named area to a grid item, where the name corresponds to a region defined in grid-template-areas — e.g., grid-area: sidebar. (2) Shorthand for row-start / column-start / row-end / column-end — e.g., grid-area: 1 / 1 / 3 / 4. The named approach is much more readable and is preferred for complex layouts.

