1. The Problem Flexbox Solves
Before Flexbox, developers used float, display: inline-block with width hacks, and even HTML tables for layout. All of these were brittle workarounds — they weren't designed for page layout.
Consider this: you want a navigation bar with a logo on the left and links on the right. Or three equal-width cards in a row. Or a footer that sticks to the bottom. Without Flexbox, each of these requires a different hack. With Flexbox, each is one or two lines of CSS.
The Core Idea
Flexbox works in two layers: the flex container (parent) controls the overall layout, and the flex items (children) can individually override their behavior. You setdisplay: flex on the parent, and everything inside it becomes a flex item.
2. Turning On Flexbox
One line. That's all it takes:
.nav {
display: flex;
}
The moment you add display: flex, three things happen automatically:
- All direct children become flex items (they line up in a row)
- Items shrink to fit their content width (instead of taking full width like block elements)
- Items stretch vertically to match the tallest sibling's height
Try it yourself — toggle display: flex on and off:
3. The Two Axes — The Mental Model That Makes Everything Click
Flexbox is a one-dimensional layout system. It works along one axis at a time. Understanding which axis you're controlling is the key to mastering Flexbox:
| Concept | When flex-direction: row (default) |
When flex-direction: column |
|---|---|---|
| Main axis | Horizontal (left → right) | Vertical (top → bottom) |
| Cross axis | Vertical | Horizontal |
justify-content controls… |
Horizontal alignment | Vertical alignment |
align-items controls… |
Vertical alignment | Horizontal alignment |
The Rule
justify-content = main axis. align-items = cross axis. Always. When you change flex-direction, the axes swap — but the rule stays the same. (CSS-Tricks: Complete Guide to Flexbox)
4. flex-direction — Which Way Do Items Flow?
| Value | Behavior |
|---|---|
row |
Left to right (default). Items sit side by side. |
row-reverse |
Right to left. Visual order flips, but DOM order stays the same. |
column |
Top to bottom. Items stack vertically (like normal block elements, but with flex superpowers). |
column-reverse |
Bottom to top. Visual order flips vertically. |
row-reverse / column-reverse for reordering content
Screen readers still read items in DOM order. Using reverse creates a disconnect between what sighted users see and what screen reader users hear. If you need visual reordering, restructure the HTML or use the order property sparingly. (MDN: Ordering flex items)
5. justify-content — Distributing Items Along the Main Axis
This is the property you'll reach for first when you want to space items out horizontally (in a row) or vertically (in a column).
| Value | What it Does | Use Case |
|---|---|---|
flex-start |
Pack items at the start (default) | Default — rarely set explicitly |
flex-end |
Pack items at the end | Right-aligning buttons in a dialog footer |
center |
Center items as a group | Centering a nav menu |
space-between |
First item at start, last at end, equal space in between | Logo left, links right (navigation bar) |
space-around |
Equal space around each item (half-space at edges) | Less common — edge spacing feels uneven |
space-evenly |
Perfectly equal space everywhere (including edges) | Icon bars, evenly spaced pill buttons |
6. align-items — Aligning Items Along the Cross Axis
| Value | What it Does |
|---|---|
stretch |
Items stretch to fill the container's cross axis (default). This is why flex items are the same height. |
flex-start |
Items align to the start of the cross axis (top, in a row layout) |
flex-end |
Items align to the end of the cross axis (bottom, in a row layout) |
center |
Items center on the cross axis — the "vertical centering" you always wanted |
baseline |
Items align so their text baselines line up (useful for different-sized text) |
The Holy Grail: Perfect Centering
Centering something both horizontally and vertically used to require hacks. With Flexbox, it's three lines:
display: flex; justify-content: center; align-items: center;
That's it. This works for any content, any size. Memorize it. (web.dev: Flexbox)
7. Interactive Playground — See It, Feel It, Learn It
Theory only gets you so far. Use the controls below to change each container property and watch the items rearrange in real-time. The CSS output panel shows you the exact code you'd write.
Try these experiments:
- Set
justify-contenttospace-between— notice how A hugs the left, D hugs the right. - Change
flex-directiontocolumn— watch everything stack vertically. Nowjustify-contentcontrols vertical spacing. - Set
align-itemstocenter— items cluster to the middle of the cross axis. - Add
gap: 16px— clean spacing without margins.
8. gap — Clean Spacing Without Margin Hacks
Before gap, developers added margins to flex items and then had to remove the margin from the first/last child. It was messy.
/* The old way — fragile */
.card {
margin-right: 16px;
}
.card:last-child {
margin-right: 0;
}
/* The Flexbox way — clean */
.card-container {
display: flex;
gap: 16px;
}
gap only creates space between items — never at the edges. It works with both flex-wrap and direction changes. Use it instead of margins whenever possible. (MDN: gap)
9. flex-wrap — What Happens When Items Don't Fit?
By default, flex items try to squeeze into one line, even if it means shrinking. Sometimes you want items to wrap to the next line instead — like a responsive grid of cards.
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 280px;
/* grow: 1, shrink: 1, basis: 280px */
/* Each card wants to be at least 280px wide */
/* If there's extra space, cards grow equally */
/* If not enough space, they wrap to next line */
}
flex: 1 1 280px + flex-wrap: wrap creates a responsive grid that requires zero media queries. Cards automatically wrap and grow to fill the row. You'll use this pattern on almost every project.
10. Flex Item Properties — Controlling Individual Items
Container properties control the group. Item properties let individual children override their behavior.
flex-grow
How much of the remaining space an item should absorb. Default is 0 (don't grow).
In the playground above, Box B has flex-grow: 1 — it absorbs all remaining horizontal space. Boxes A and C stay content-sized. Try giving A and C flex-grow: 1 too — they'll split the space equally.
flex-shrink
How much an item should shrink when there isn't enough space. Default is 1 (shrink proportionally). Set to 0 to prevent shrinking.
flex-basis
The ideal starting size of an item before growing/shrinking kicks in. Think of it like a suggestion: "I'd like to be this wide, but I'm flexible." Default is auto (use the item's width or content size).
The flex shorthand
In practice, you almost always use the shorthand. Here are the patterns that matter:
| Shorthand | Means | When to Use |
|---|---|---|
flex: 1 |
flex-grow: 1; flex-shrink: 1; flex-basis: 0% |
Equal-width items that fill the row |
flex: 0 0 auto |
Don't grow, don't shrink, use natural size | Fixed-size items (icons, avatars) |
flex: 1 1 200px |
Grow and shrink, but start at 200px | Responsive cards with a minimum width |
flex: none |
flex: 0 0 auto — completely inflexible |
Elements that must keep their exact size |
11. Real-World Patterns You'll Build Every Week
Pattern 1: Navigation Bar
Key technique: justify-content: space-between pushes the logo left and links right. The <ul> is also a flex container (flex containers can nest!).
Pattern 2: Centered Hero Section
Key technique: flex-direction: column stacks children vertically. justify-content: center + align-items: center centers everything in both directions.
Pattern 3: Card Row with Equal Heights
Key technique: flex: 1 on each card makes them equal width. Flexbox's default align-items: stretch makes them equal height — no JavaScript needed.
12. Knowledge Check
🧠 Test Your Understanding
What does display: flex affect?
In a flex container with the default flex-direction: row, what does justify-content control?
You want to center a single element both horizontally and vertically inside its parent. Which combination works?
What does flex: 1 on a flex item do?
What is the advantage of gap over adding margin to flex items?
You have a navigation bar. You want the logo on the far left and the links on the far right. Which property achieves this?
Review the sections above for any questions you got wrong. The playground is your best friend — experiment until it clicks.
13. Write It From Memory
Without scrolling up, fill in the CSS to create a navigation bar with the logo on the left and links on the right, vertically centered:
14. Build Challenge: Portfolio Layout with Flexbox
Take your portfolio page from previous lessons and rebuild the layout using Flexbox. No float, no inline-block — Flexbox only.
- Create
practices/lesson6-portfolio.htmlandpractices/lesson6-style.css - Build a navigation bar:
- Logo/name on the left, 3+ links on the right
- Use
display: flex+justify-content: space-between - Vertically center with
align-items: center
- Build a hero section:
- Centered heading, subtitle, and a button
- Use
flex-direction: column+ centering - Give it a minimum height:
min-height: 60vh
- Build a 3-card project grid:
- Each card has a title and description
- Equal width using
flex: 1 - Use
gapfor spacing
- Build a footer with two groups:
- Copyright text on the left, social links on the right
- Same
space-betweenpattern as the nav
Primary Source: CSS-Tricks: A Complete Guide to Flexbox is the canonical Flexbox reference. Bookmark it — you'll come back to it for years. Also: MDN: Basic concepts of flexbox and Kevin Powell for visual demonstrations.
Finished the build? Type /teach and show me your portfolio. I'll review the layout before we move on to CSS Grid.