Full Stack Web Development
Chapter 4: CSS Grid ��� Two-Dimensional Layout Mastery
Chapter 4: CSS Grid — Two-Dimensional Layout Mastery
4.1 Learning Objectives
4.2 Prerequisites
4.3 Introduction
4.4 Real-Life Analogy
4.5 Why This Topic Exists
4.6 Where It Is Used
4.7 Detailed Explanation: Grid Terminology
4.8 Turning On Grid
4.9 The fr Unit — Fractional Space
4.10 The repeat() Function — Avoiding Repetition
4.11 minmax() and auto-fit/auto-fill — Truly Responsive Grids
4.12 Placing Items Explicitly — Grid Line Numbers
4.13 grid-template-areas — Naming Your Layout (Highly Readable)
4.14 Grid vs. Flexbox — When to Use Which
4.15 Common Beginner Mistakes
4.16 Best Practices
4.17 Interview Questions
4.18 Practice Questions
4.19 Coding Exercises
4.20 Mini Challenge
4.21 MINI PROJECT: Photo Gallery + Dashboard Layout
4.22 Summary
4.23 Key Takeaways
Chapter 4: CSS Grid — Two-
Dimensional Layout Mastery
4.1 Learning Objectives
By the end of this chapter, you will be able to:
1. Explain what CSS Grid is and how it differs fundamentally from
Flexbox.
2. Define grid containers, grid tracks, grid lines, grid cells, and grid
areas.
3. Build layouts using grid-template-columns, grid-template-rows, and
grid-template-areas.
4. Use the fr unit and repeat()/minmax() functions to build flexible,
self-adjusting grids.
5. Place items precisely using grid line numbers and named areas.
6. Combine Grid (for overall page layout) with Flexbox (for
component-level alignment) — the professional standard approach.
7. Build a mini project: a Photo Gallery + Dashboard Layout.
4.2 Prerequisites
Chapters 1–3 completed (HTML5, CSS3, Flexbox).
Comfort with the Box Model and Flexbox’s main/cross axis
concept, since we will constantly compare Grid to Flexbox.
4.3 Introduction
In Chapter 3, we learned Flexbox can arrange items in a single row
OR a single column — a one-dimensional system. But what about a
true grid, like a spreadsheet or a photo gallery, where you need
control over BOTH rows AND columns at the same time?
You can force Flexbox to fake a grid using flex-wrap, but the columns
won’t line up perfectly if row heights differ, and you have limited
control over exact row/column sizing. CSS Grid was built specifically
to solve two-dimensional layout — rows and columns together, as a
single connected system.
4.4 Real-Life Analogy
Think of Flexbox as arranging a single shelf of books — one row or
one column at a time.
CSS Grid is like designing the entire bookshelf unit — multiple
shelves and columns of compartments, where you can say: “This
section spans 2 columns and 1 row. That section spans 1 column and 3
rows.” You’re designing the whole structure at once, not just one line
of it.
Another analogy: think of a city laid out on a grid — streets running
north-south (columns) and avenues running east-west (rows). A
building (grid item) can occupy one city block, or be a large complex
spanning multiple blocks. CSS Grid gives you this same power over
your page layout.
FLEXBOX: one row OR one column CSS GRID: rows AND columns
together
[1][2][3] [1][2][3]
[4][5][6]
[7][8][9]
4.5 Why This Topic Exists
Before CSS Grid (standardized around 2017), true 2D layouts required
tables (semantically wrong — tables are for data, not layout, as
covered in Chapter 1), or complex combinations of floats and fixed-
width columns that broke easily.
CSS Grid was designed by the CSS Working Group to finally give web
developers a native, purpose-built system for the same kind of
layout power that design tools like Photoshop or print layout software
had offered for decades — precise control over rows, columns, and
item placement, all in plain CSS.
4.6 Where It Is Used
Full page layouts (header, sidebar, main content, footer — all
positioned as one connected grid).
Photo galleries and image grids.
Dashboards with widgets of varying sizes.
E-commerce product listing grids.
Complex admin panels and CMS interfaces.
Modern CSS frameworks (Tailwind CSS’s grid utilities, Bootstrap
5’s grid system) are built on top of these same native CSS Grid
concepts.
4.7 Detailed Explanation: Grid
Terminology
Before writing code, we must understand Grid’s vocabulary — this is
where most beginners get lost, so we go slowly.
COLUMN LINES
1 2 3 4
│ │ │ │
ROW 1 ──┼─────┼─────┼─────┼── LINE 1
│ A │ B │ C │
ROW 2 ──┼─────┼─────┼─────┼── LINE 2
│ D │ E │ F │
ROW 3 ──┼─────┼─────┼─────┼── LINE 3
Term Meaning
The parent element with
Grid Container
display: grid applied.
A direct child of the grid
Grid Item
container.
The dividing lines that make up
the grid structure — both
Grid Line vertical (column lines) and
horizontal (row lines). Numbered
starting from 1.
The space between two adjacent
Grid Track grid lines — essentially a row or
a column.
The smallest unit — a single
Grid Cell space at the intersection of one
row track and one column track.
A rectangular group of cells,
Grid Area which can span multiple rows
and/or columns.
Gutter/Gap The spacing between tracks.
4.8 Turning On Grid
.container {
display: grid;
grid-template-columns: 200px 200px 200px; /* 3 columns, each
200px wide */
grid-template-rows: 100px 100px; /* 2 rows, each
100px tall */
gap: 16px;
}
This creates a 3-column, 2-row grid — 6 total cells — and any direct
children are automatically placed into these cells, left-to-right, top-to-
bottom, by default.
Syntax Breakdown
grid-template-columns → defines the number of columns AND each
column’s width, as a space-separated list.
grid-template-rows → defines the number of rows AND each row’s
height, as a space-separated list.
gap → spacing between both rows and columns (same property
name as in Flexbox — consistent across both systems).
4.9 The fr Unit — Fractional Space
The most powerful and distinctly “Grid” unit is fr (fraction),
representing a fraction of the available space in the grid container.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 3 EQUAL-width columns,
filling 100% of space */
}
.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr; /* first column is TWICE
as wide as the other two */
}
Why fr is powerful: Unlike percentages, fr automatically accounts
for gaps and fixed-width tracks mixed in alongside it:
.container {
display: grid;
grid-template-columns: 200px 1fr 1fr;
/* first column: exactly 200px.
remaining space is split evenly between the other two columns
*/
}
This mixed unit approach (fixed px + flexible fr) is extremely common
for real layouts — e.g., a fixed-width sidebar next to a flexible main
content area.
4.10 The repeat() Function — Avoiding
Repetition
Writing 1fr 1fr 1fr 1fr 1fr 1fr for a 6-column grid is tedious. The
repeat() function solves this:
.container {
display: grid;
grid-template-columns: repeat(6, 1fr); /* identical to: 1fr 1fr
1fr 1fr 1fr 1fr */
}
Syntax: repeat(count, track-size). You can even repeat a pattern:
grid-template-columns: repeat(3, 1fr 2fr);
/* equivalent to: 1fr 2fr 1fr 2fr 1fr 2fr (repeats the PAIR three
times) */
4.11 minmax() and auto-fit/auto-fill — Truly
Responsive Grids
This next pattern is one of the most useful, industry-standard
techniques in modern CSS — a self-adjusting grid that needs zero
media queries:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
Let’s break this down completely, piece by piece:
minmax(200px, 1fr) → each column must be at least 200px wide,
but can grow up to 1fr (an equal share of remaining space) if
there’s room.
repeat(auto-fit, ...) → instead of specifying a fixed number of
columns, auto-fit tells the browser: “Fit as many 200px+
columns as will comfortably fit in the available width, and
stretch them to fill any leftover space.”
The result: On a wide desktop screen, you might get 5 columns. On a
tablet, 3 columns. On a phone, 1 column. All automatically, with zero
media queries and zero JavaScript.
Tip: auto-fit vs auto-fill — the difference is subtle: auto-fit
collapses empty leftover tracks (letting existing items stretch to
fill the space), while auto-fill keeps empty tracks reserved
(items stay their minmax size, not stretching to fill leftover space).
In practice, auto-fit is what you want about 95% of the time for
responsive card/gallery grids.
4.12 Placing Items Explicitly — Grid Line
Numbers
Sometimes you want an item to span multiple cells, rather than
occupying just one. You do this using grid line numbers.
.item-a {
grid-column: 1 / 3; /* start at column line 1, end at column
line 3 → spans 2 columns */
grid-row: 1 / 2; /* start at row line 1, end at row line 2
→ spans 1 row */
}
1 2 3 4 (column lines)
1 ┌─────────────┬─────┐
│ item-a │ │
2 ├─────────────┼─────┤
│ │ │
3 └─────────────┴─────┘
Syntax breakdown of grid-column: 1 / 3: - 1 = the starting grid line.
- / = separator (read as “to” or “through”). - 3 = the ending grid line. -
The item occupies the space between line 1 and line 3 — which is 2
column tracks wide.
The span keyword — an alternative, often more
convenient syntax
.item-a {
grid-column: span 2; /* "span 2 columns starting from wherever
this item is placed" */
}
This is often preferred because you don’t need to calculate exact line
numbers — just say how many tracks to span.
4.13 grid-template-areas — Naming Your
Layout (Highly Readable)
This is arguably the most beginner-friendly and readable way to build
a full page layout with Grid.
.page {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
<div class="page">
<header class="header">Header</header>
<aside class="sidebar">Sidebar</aside>
<main class="main">Main Content</main>
<footer class="footer">Footer</footer>
</div>
Explanation
grid-template-areas uses a visual, string-based grid map. Each
quoted string represents one row; each word represents which
named area occupies that cell.
Notice "sidebar" appears in all 3 rows — this tells Grid the sidebar
spans all 3 rows, forming one tall column on the left.
Each child element is assigned to a named area using grid-area:
<name>;, which must exactly match a name used in grid-template-
areas.
This produces a full classic page layout: a full-height sidebar, with
header/main/footer stacked in the remaining space — in about 10
lines of CSS, fully readable even to someone unfamiliar with the
code, because the ASCII-art-like template visually resembles the
actual page layout.
┌────────┬─────────────────────┐
│ │ Header │
│Sidebar ├─────────────────────┤
│ │ │
│ │ Main │
│ │ │
│ ├─────────────────────┤
│ │ Footer │
└────────┴─────────────────────┘
4.14 Grid vs. Flexbox — When to Use
Which
Question Use Flexbox Use Grid
Do you need to control ONE
dimension (a row OR a ✅
column)?
Do you need to control ROWS
✅
and COLUMNS together?
Is content driving the layout
✅
size (e.g., a row of nav links)?
Is the LAYOUT structure
defined first, with content
✅
filling it (e.g., a page
skeleton)?
Building an overall page
layout ✅
(header/sidebar/main/footer)?
Aligning items within a single
component (buttons in a ✅
toolbar)?
✅ Best Practice, used constantly in real projects: Use CSS
Grid for the big picture (overall page structure), and Flexbox
for the small pieces (aligning content inside individual
components, like centering text in a button, or spacing icons in a
toolbar). They are not competitors — they are complementary
tools, and most real-world pages use both together.
4.15 Common Beginner Mistakes
1. Confusing Grid and Flexbox use cases — trying to force a full
2D page layout using nested Flexbox rows, when Grid would be far
simpler and more maintainable.
2. Forgetting that grid line numbers start at 1, not 0.
3. Mismatched names in grid-template-areas and grid-area — a
single typo silently breaks the layout with no error message, just a
misplaced element.
4. Using fixed pixel columns everywhere, missing out on the
responsive power of fr, minmax(), and auto-fit.
5. Not using gap, and instead manually adding margins to grid items
(unnecessary — Grid’s gap handles this natively and more cleanly).
6. Overcomplicating simple one-directional layouts with Grid
when Flexbox would be simpler — remember the “Grid vs Flexbox”
decision table above.
4.16 Best Practices
Use grid-template-areas for full page layouts — it’s the most self-
documenting, readable approach.
Use repeat(auto-fit, minmax(...)) for responsive card/gallery
grids that need zero media queries.
Combine fr units with fixed-width tracks (like a sidebar) for hybrid
flexible/fixed layouts.
Use gap instead of margins for spacing between grid items.
Reserve CSS Grid for 2D structural layout; use Flexbox for 1D
component-level alignment inside grid cells.
4.17 Interview Questions
1. What is the core difference between CSS Grid and Flexbox?
2. What does the fr unit represent, and how is it different from a
percentage?
3. Explain what repeat(auto-fit, minmax(200px, 1fr)) does, in plain
English.
4. What is the difference between auto-fit and auto-fill?
5. What are grid lines, and how are they numbered?
6. What is grid-template-areas, and why is it considered
readable/self-documenting?
7. When would you choose Grid over Flexbox, and vice versa?
8. What does grid-column: span 2; do?
9. Can a Flexbox container be placed inside a CSS Grid item? Explain
why or why not.
10. What CSS property connects a grid item to a named area defined
in grid-template-areas?
4.18 Practice Questions
1. Write CSS for a grid with 4 equal-width columns and a 20px gap.
2. Modify that grid so the first column is twice as wide as the other
three.
3. Explain, using the diagram style from this chapter, what grid-
column: 2 / 4; would do to an item’s placement.
4. Design (on paper or in ASCII) a grid-template-areas layout for a
blog post page with a header, a main article area, a related-posts
sidebar, and a footer.
5. Why is auto-fit usually preferred over a fixed repeat(4, 1fr) for a
photo gallery meant to work on all screen sizes?
4.19 Coding Exercises
Exercise 1: Build a simple 3x3 grid of colored boxes using grid-
template-columns and grid-template-rows.
Exercise 2: Build a responsive photo gallery using repeat(auto-fit,
minmax(150px, 1fr)) — test it by resizing your browser window.
Exercise 3: Build a page layout (header, sidebar, main, footer) using
grid-template-areas.
Exercise 4: Create a grid item that spans 2 columns and 2 rows,
using either line numbers or the span keyword.
Exercise 5: Combine Grid and Flexbox: build a Grid-based page
layout where the header itself uses Flexbox internally to space out a
logo and nav links (just like Chapter 3’s navbar).
4.20 Mini Challenge
Build a Dashboard Layout with: - A grid-template-areas layout:
sidebar (full height), topbar, and a main content area. - Inside the
main content area, a responsive grid of “widget” cards using
repeat(auto-fit, minmax(220px, 1fr)). - Inside the topbar, use Flexbox
to align a search box on the left and a user avatar/profile on the right.
This challenge deliberately forces you to combine Grid (structural)
and Flexbox (component-level) in one realistic layout — exactly how
real production dashboards (like admin panels) are built.
4.21 MINI PROJECT: Photo Gallery +
Dashboard Layout
Project Goal
Build a two-part project demonstrating Grid’s two superpowers: (1) a
fully responsive photo gallery, and (2) a structural full-page dashboard
layout combining Grid and Flexbox.
Part 1: Responsive Photo Gallery
HTML
<section class="gallery">
<div class="gallery__item"><img src="[Link]" alt="Mountain
landscape at sunrise"></div>
<div class="gallery__item"><img src="[Link]" alt="City
skyline at night"></div>
<div class="gallery__item"><img src="[Link]" alt="Ocean
waves on a beach"></div>
<div class="gallery__item"><img src="[Link]" alt="Forest
path in autumn"></div>
<div class="gallery__item"><img src="[Link]" alt="Desert
dunes at dusk"></div>
<div class="gallery__item"><img src="[Link]" alt="Snowy
mountain peak"></div>
</section>
CSS
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
padding: 24px;
}
.gallery__item img {
width: 100%;
height: 200px;
object-fit: cover; /* crops image to fill the box without
distortion */
border-radius: 8px;
display: block; /* removes small inline-image whitespace
gap below images */
}
Explanation: - object-fit: cover is a key property for image grids: it
makes the image fill its box completely (like background-size: cover
did in Chapter 2), cropping edges as needed while preserving the
image’s natural aspect ratio — preventing squished/stretched photos.
- display: block on the <img> removes a subtle default browser quirk
where inline images leave a tiny gap of whitespace below them
(images are inline by default, and inline elements respect line-
height/baseline spacing, which creates that gap).
Part 2: Dashboard Layout
HTML
<div class="dashboard">
<aside class="dashboard__sidebar">Sidebar</aside>
<header class="dashboard__topbar">
<input type="text" placeholder="Search..."
class="dashboard__search">
<div class="dashboard__profile"> Ayesha</div>
</header>
<main class="dashboard__main">
<div class="widget">Widget 1</div>
<div class="widget">Widget 2</div>
<div class="widget">Widget 3</div>
<div class="widget">Widget 4</div>
</main>
</div>
CSS
.dashboard {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-rows: 70px 1fr;
grid-template-areas:
"sidebar topbar"
"sidebar main";
min-height: 100vh;
}
.dashboard__sidebar {
grid-area: sidebar;
background-color: #0f172a;
color: white;
padding: 20px;
}
.dashboard__topbar {
grid-area: topbar;
display: flex; /* Flexbox INSIDE a Grid item
*/
justify-content: space-between;
align-items: center;
padding: 0 24px;
border-bottom: 1px solid #e2e8f0;
}
.dashboard__search {
padding: 8px 12px;
border: 1px solid #cbd5e1;
border-radius: 6px;
}
.dashboard__main {
grid-area: main;
display: grid; /*
Grid INSIDE a Grid item */
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
padding: 24px;
background-color: #f8fafc;
}
.widget {
background-color: white;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
Step-by-Step Explanation
1. .dashboard uses grid-template-areas to lay out the big-picture
structure: a sidebar spanning both rows on the left, with a topbar
and main content stacked on the right.
2. .dashboard__topbar uses display: flex — this is Grid and Flexbox
working together: the topbar is a Grid item (positioned by the
outer grid), but internally it’s a Flex container, spacing out the
search box and profile using justify-content: space-between,
exactly like our Chapter 3 navbar.
3. .dashboard__main uses display: grid again — a nested grid,
independent of the outer page grid, laying out the widget cards
responsively using the same auto-fit/minmax() pattern from our
photo gallery.
4. This nested structure (Grid → Flexbox → Grid) reflects exactly how
real-world dashboards (like Notion, Trello, or admin panels) are
actually built: an outer Grid skeleton, with Flexbox and Grid used
situationally inside each region based on what that region needs.
Expected Output (conceptually)
┌─────────┬─────────────────────────────────────┐
│ │ [search box] Ayesha │
│ Sidebar ├─────────────────────────────────────┤
│ │ [Widget 1] [Widget 2] │
│ │ [Widget 3] [Widget 4] │
└─────────┴─────────────────────────────────────┘
✅ Checkpoint: Resize the browser window. The sidebar stays
fixed at 220px, while the topbar and widget area flexibly adjust.
The widgets reflow from 2 columns down to 1 column on narrow
screens — all without a single media query, thanks to auto-fit +
minmax().
4.22 Summary
CSS Grid is a two-dimensional layout system, handling rows and
columns together as one connected structure.
Key building blocks: grid-template-columns, grid-template-rows,
grid-template-areas, and the fr unit.
repeat(auto-fit, minmax(min, 1fr)) is the industry-standard
pattern for responsive card/gallery grids with zero media queries.
grid-template-areas provides a highly readable, self-documenting
way to define full-page layouts.
Grid and Flexbox are complementary, not competing: Grid
handles the big-picture 2D structure; Flexbox handles 1D
alignment within individual components.
We built both a responsive Photo Gallery and a full Dashboard
Layout combining Grid (structure) with Flexbox (component
alignment).
4.23 Key Takeaways
✅ CSS Grid = two-dimensional layout (rows AND columns
together).
✅ fr = a fraction of available space; far more flexible than fixed
pixels or percentages.
✅ repeat(auto-fit, minmax(...)) builds fully responsive grids
without media queries.
✅ grid-template-areas is the most readable way to define full-page
layouts.
✅ Grid (structure) + Flexbox (component alignment) together form
the professional standard toolkit for modern CSS layout.
✅ You can now build genuinely responsive, professional page
layouts — next, we formalize Responsive Design with media
queries and mobile-first principles.
Next: Chapter 5 — Responsive Design, where we learn media
queries, mobile-first design, and how to make any layout adapt
beautifully to every screen size.