Introduction to HTML & CSS · Lesson 3 of 5
Flexbox & CSS Grid for Modern Layouts
CSS Flexbox and Grid
Before Flexbox and Grid, CSS layouts were hacked together with floats and positioning. Now these two tools handle 95% of everything you need. Learn both — they complement each other.
Rule of thumb: Flexbox for one-dimensional layouts (row OR column). Grid for two-dimensional layouts (rows AND columns simultaneously).
CSS Flexbox
Apply display: flex to a container to turn its direct children into flex items.
The Main Axis and Cross Axis
The key mental model:
- Main axis = the direction flex items flow (
flex-direction) - Cross axis = perpendicular to main axis
.container {
display: flex;
flex-direction: row; /* default: left to right */
/* flex-direction: column; top to bottom */
/* flex-direction: row-reverse; right to left */
/* flex-direction: column-reverse; bottom to top */
}Alignment Properties
.container {
display: flex;
/* Align along MAIN axis */
justify-content: flex-start; /* default — pack at start */
justify-content: flex-end; /* pack at end */
justify-content: center; /* center */
justify-content: space-between; /* first/last at edges, rest evenly spaced */
justify-content: space-around; /* equal space around each item */
justify-content: space-evenly; /* equal space between all items and edges */
/* Align along CROSS axis (single line) */
align-items: stretch; /* default — fill cross axis */
align-items: flex-start; /* align to start of cross axis */
align-items: flex-end; /* align to end */
align-items: center; /* center vertically (if row direction) */
align-items: baseline; /* align text baselines */
/* Align multiple lines (only when flex-wrap: wrap) */
align-content: flex-start;
align-content: center;
align-content: space-between;
}Wrapping
.container {
flex-wrap: nowrap; /* default — overflow if items don't fit */
flex-wrap: wrap; /* wrap to next line */
flex-wrap: wrap-reverse;
}Gap
.container {
display: flex;
gap: 16px; /* space between all items */
gap: 16px 8px; /* row-gap column-gap */
row-gap: 16px;
column-gap: 8px;
}Flex Item Properties
.item {
/* How much the item grows relative to siblings (default: 0 = don't grow) */
flex-grow: 1; /* take up remaining space */
flex-grow: 2; /* take twice as much remaining space as flex-grow:1 items */
/* How much the item shrinks (default: 1 = can shrink) */
flex-shrink: 0; /* don't shrink — keep its width */
/* Starting size before grow/shrink */
flex-basis: 200px; /* start at 200px, then grow/shrink */
flex-basis: auto; /* use width/content size */
flex-basis: 0; /* start from nothing, then grow */
/* Shorthand: grow shrink basis */
flex: 1 1 auto; /* default */
flex: 1; /* grow:1, shrink:1, basis:0 — most common */
flex: 0 0 200px; /* fixed 200px — don't grow, don't shrink */
/* Override align-items for this specific item */
align-self: center;
/* Change order (default: 0) */
order: -1; /* move to beginning */
order: 1; /* move to end */
}Flexbox Patterns
Centered Content (most common CSS question)
.centered {
display: flex;
justify-content: center;
align-items: center;
/* For full-screen centering: */
min-height: 100vh;
}Navigation Bar
.nav {
display: flex;
align-items: center;
padding: 0 24px;
height: 64px;
}
.nav-logo { margin-right: auto; } /* pushes everything else to the right */
.nav-links {
display: flex;
gap: 8px;
}Equal-Width Cards
.card-row {
display: flex;
gap: 16px;
}
.card {
flex: 1; /* all cards share space equally */
}Sticky Footer
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main { flex: 1; } /* takes all available space, pushes footer down */
footer { /* natural height */ }CSS Grid
Grid divides a container into rows and columns, and you place items into cells.
Defining the Grid
.grid {
display: grid;
/* Define columns */
grid-template-columns: 200px 200px 200px; /* 3 fixed columns */
grid-template-columns: 1fr 1fr 1fr; /* 3 equal columns */
grid-template-columns: 200px 1fr; /* fixed + flexible */
grid-template-columns: repeat(3, 1fr); /* shorthand */
grid-template-columns: repeat(3, minmax(200px, 1fr)); /* min 200px, share rest */
/* Define rows */
grid-template-rows: 80px 1fr 60px; /* fixed header, flexible main, fixed footer */
grid-auto-rows: 200px; /* all implicit rows are 200px */
grid-auto-rows: minmax(150px, auto); /* min 150px, grow with content */
/* Gap */
gap: 16px;
column-gap: 16px;
row-gap: 8px;
}Responsive Grid with auto-fill
/* Auto-fill: as many columns as fit, minimum 250px each */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
/* auto-fit vs auto-fill:
auto-fill: keeps empty columns (items don't stretch to fill row)
auto-fit: collapses empty columns (items stretch to fill row) */Placing Items
/* By line number (1-based, negative counts from end) */
.item {
grid-column: 1 / 3; /* from column line 1 to 3 (spans 2 columns) */
grid-column: 1 / -1; /* full width (from line 1 to last line) */
grid-column: span 2; /* span 2 columns from current position */
grid-row: 1 / 2;
grid-row: span 2; /* span 2 rows */
}Named Template Areas
.layout {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 64px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }Grid Patterns
Holy Grail Layout
body {
display: grid;
grid-template-columns: 240px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
min-height: 100vh;
gap: 0;
}
header { grid-area: header; }
.sidebar{ grid-area: sidebar; }
main { grid-area: content; }
aside { grid-area: aside; }
footer { grid-area: footer; }Magazine / Asymmetric Grid
.magazine {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.featured {
grid-column: span 2;
grid-row: span 2;
}Image Gallery with Masonry-like Effect
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px;
gap: 8px;
}
.gallery-item:nth-child(3n+1) { grid-row: span 2; } /* every 3rd-1 is taller */Flexbox vs Grid — When to Use Each
| Scenario | Use | |----------|-----| | Navigation bar (horizontal) | Flexbox | | Card row (equal widths) | Either | | Full-page layout (header/sidebar/main/footer) | Grid | | Responsive card grid | Grid (auto-fill) | | Center one element | Flexbox | | Item grows to fill remaining space | Flexbox | | Two-dimensional overlap/spanning | Grid | | Unknown number of items | Flexbox |
They work together — use Grid for page layout, Flexbox inside components.
Complete Example: App Layout
<!-- HTML -->
<body class="layout">
<header class="header">
<a href="/" class="logo">App</a>
<nav class="nav">
<a href="/dashboard">Dashboard</a>
<a href="/courses">Courses</a>
<a href="/settings">Settings</a>
</nav>
<button class="btn">Sign In</button>
</header>
<aside class="sidebar">...</aside>
<main class="main">
<div class="cards">
<div class="card">...</div>
<div class="card">...</div>
<div class="card">...</div>
</div>
</main>
<footer class="footer">© 2026</footer>
</body>/* Page layout — Grid */
.layout {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr 48px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; padding: 24px; }
.footer { grid-area: footer; }
/* Header — Flexbox */
.header {
display: flex;
align-items: center;
padding: 0 24px;
gap: 16px;
border-bottom: 1px solid #e5e7eb;
}
.nav { display: flex; gap: 4px; }
.btn { margin-left: auto; }
/* Cards — responsive Grid */
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
/* Card — Flexbox for internal layout */
.card {
display: flex;
flex-direction: column;
border-radius: 12px;
overflow: hidden;
}
.card-content { flex: 1; padding: 16px; } /* grows to push footer down */
.card-footer { padding: 12px 16px; } /* stays at bottom */Key Takeaways
- Flexbox = one-dimensional,
justify-contenton main axis,align-itemson cross axis - Grid = two-dimensional,
grid-template-columns/rowsdefine structure,grid-areaplaces items gapworks in both — prefer it over margins between itemsrepeat(auto-fill, minmax(250px, 1fr))is the magic responsive grid patternflex: 1makes an item fill remaining space — use it for the main content area- Named template areas (
grid-template-areas) make complex layouts readable