Module 7

Layout: Flexbox

Flex Container • Items • Alignment • Wrapping • Patterns

📐 Why Flexbox Changes Everything

Before Flexbox, CSS layout was a struggle. Developers relied on float, display: inline-block, and creative hacks just to put two boxes side by side. Centering something vertically was famously difficult. Flexbox solved all of this with a single, intuitive system.

Flexbox (Flexible Box Layout) is a one-dimensional layout method. It arranges items along a single axis — either a row or a column. It excels at distributing space, aligning items, and building responsive patterns with minimal code.

💡
The Bookshelf Analogy: Imagine a bookshelf. Without Flexbox, you have to manually measure and position every book. With Flexbox, you tell the shelf: "arrange these books in a row, space them evenly, and make them all the same height." The shelf handles the math. That is what display: flex does — it turns a container into a smart shelf.

🎯 By the end of this module, you will:

  • Understand the flex container / flex item relationship
  • Control layout direction with flex-direction and flex-wrap
  • Align items along the main axis with justify-content
  • Align items along the cross axis with align-items and align-content
  • Size flex items with flex-grow, flex-shrink, and flex-basis
  • Use the gap property for clean spacing
  • Build real-world patterns: navbars, card rows, centering, and sidebar layouts

📦 The Flex Container

Flexbox works with two roles: the flex container (the parent) and flex items (the direct children). You activate Flexbox by setting display: flex on the parent. Immediately, all direct children become flex items and arrange themselves in a row.

CSS
Try it →
/* The parent becomes a flex container */
.container {
  display: flex;
}

/* Children automatically become flex items */
.item {
  padding: 20px;
  background: #3b82f6;
  color: white;
  border-radius: 8px;
}
⚠️
Direct children only! Flexbox only affects the direct children of the flex container. Grandchildren and deeper elements are not flex items — they follow normal flow unless you set display: flex on their own parent too.

flex-direction

By default, flex items flow in a row (left to right). You can change this with flex-direction. The direction you choose defines the main axis — the primary direction items are laid out.

flex-direction Values

1 rowItems flow left → right (default). Main axis is horizontal.
2 row-reverseItems flow right → left. Main axis is horizontal, reversed.
3 columnItems flow top → bottom. Main axis is vertical.
4 column-reverseItems flow bottom → top. Main axis is vertical, reversed.
CSS
Try it →
/* Row (default) — horizontal layout */
.row {
  display: flex;
  flex-direction: row;
  gap: 12px;
}

/* Column — vertical layout */
.column {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.item {
  padding: 16px 24px;
  background: #6366f1;
  color: white;
  border-radius: 8px;
  font-weight: 600;
}

flex-wrap

By default, flex items are forced onto one line — they will shrink rather than wrap. Set flex-wrap: wrap to allow items to flow onto multiple lines when they run out of space.

CSS
Try it →
/* Allow items to wrap onto new lines */
.wrap-container {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.tag {
  padding: 8px 16px;
  background: #f1f5f9;
  border-radius: 20px;
  font-size: 0.9rem;
}

flex-wrap Values

1 nowrapAll items stay on one line (default). Items shrink if needed.
2 wrapItems wrap onto new lines when the container runs out of space.
3 wrap-reverseItems wrap onto new lines above (or to the left in column mode).
💡
Shorthand: flex-flow You can combine flex-direction and flex-wrap into one shorthand: flex-flow: row wrap;. This is equivalent to writing flex-direction: row; flex-wrap: wrap;.

↔️ Main Axis Alignment

The justify-content property controls how flex items are distributed along the main axis. In a row, that means horizontal spacing. In a column, it means vertical spacing. This is one of the most-used Flexbox properties.

justify-content Values

1 flex-startItems packed to the start (default).
2 flex-endItems packed to the end.
3 centerItems centered along the main axis.
4 space-betweenFirst item at start, last at end, equal space between each item.
5 space-aroundEqual space around each item. Items have half-size spaces on the edges.
6 space-evenlyExactly equal space between and around all items.
CSS
Try it →
/* space-between — most common for navbars */
.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  background: #1e293b;
  color: white;
  border-radius: 8px;
}

/* center — perfect for centering content */
.centered {
  display: flex;
  justify-content: center;
  padding: 24px;
  background: #f1f5f9;
  border-radius: 8px;
}

/* space-evenly — equal gaps everywhere */
.even {
  display: flex;
  justify-content: space-evenly;
  padding: 24px;
  background: #f1f5f9;
  border-radius: 8px;
}

↕️ Cross Axis Alignment

The cross axis is perpendicular to the main axis. In a row layout, the cross axis is vertical. align-items controls how items are positioned on this axis.

align-items

This property aligns all flex items along the cross axis. The most common use case: making items the same height, or vertically centering text next to an icon.

align-items Values

1 stretchItems stretch to fill the container height (default).
2 flex-startItems aligned to the top (start of cross axis).
3 flex-endItems aligned to the bottom (end of cross axis).
4 centerItems centered vertically.
5 baselineItems aligned by their text baseline — useful when items have different font sizes.
CSS
Try it →
/* Stretch (default) — items match the tallest */
.stretch {
  display: flex;
  align-items: stretch;
  gap: 12px;
  min-height: 120px;
  background: #f8fafc;
  padding: 12px;
  border-radius: 8px;
}

/* Center — vertically centered */
.v-center {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 120px;
  background: #f8fafc;
  padding: 12px;
  border-radius: 8px;
}

.item {
  padding: 16px;
  background: #6366f1;
  color: white;
  border-radius: 6px;
}

align-content

align-content controls the spacing between wrapped lines (not individual items). It only has an effect when flex-wrap: wrap is set and there are multiple lines. It takes the same values as justify-content.

💡
align-items vs. align-content align-items positions individual items within their line. align-content positions the lines themselves within the container. If you only have one line (no wrapping), align-content has no effect.

🧩 Flex Items

While the container controls the overall layout, each flex item can control how it individually sizes and positions itself. The three key properties are flex-grow, flex-shrink, and flex-basis.

flex-grow

flex-grow controls how remaining space is distributed. A value of 0 (default) means the item won't grow. A value of 1 means it will absorb its share of leftover space. If two items have flex-grow: 1, they share equally; if one has 2 and the other 1, the first gets twice as much extra space.

CSS
Try it →
.container {
  display: flex;
  gap: 12px;
}

/* This item stays at its natural size */
.sidebar {
  flex-grow: 0;
  width: 200px;
  background: #e2e8f0;
  padding: 16px;
  border-radius: 8px;
}

/* This item grows to fill all remaining space */
.main {
  flex-grow: 1;
  background: #dbeafe;
  padding: 16px;
  border-radius: 8px;
}

flex-shrink

flex-shrink controls how items give up space when the container is too small. The default is 1 — all items shrink equally. Set flex-shrink: 0 to prevent an item from shrinking (useful for fixed-width elements like logos or icons).

flex-basis

flex-basis sets the initial size of a flex item before growing or shrinking is applied. Think of it as the "ideal" size. It accepts any length value (px, rem, %) or the keyword auto (default — uses the item's width or content size).

The flex Shorthand

The flex shorthand combines all three: flex: grow shrink basis. In practice, you'll use a few common patterns:

Common flex Values

1 flex: 1Same as flex: 1 1 0%. Item grows and shrinks equally, starting from zero width. All items with flex: 1 share space equally.
2 flex: autoSame as flex: 1 1 auto. Like flex: 1 but starts from the item's natural size before distributing space.
3 flex: noneSame as flex: 0 0 auto. Item is completely inflexible — no growing, no shrinking.
4 flex: 0 0 250pxFixed at 250px. Won't grow or shrink. Common for fixed sidebars.
CSS
Try it →
.layout {
  display: flex;
  gap: 16px;
  min-height: 200px;
}

/* Fixed sidebar — never grows or shrinks */
.sidebar {
  flex: 0 0 220px;
  background: #1e293b;
  color: white;
  padding: 20px;
  border-radius: 8px;
}

/* Main content — takes all remaining space */
.content {
  flex: 1;
  background: #f1f5f9;
  padding: 20px;
  border-radius: 8px;
}

order

By default, flex items appear in their HTML source order. The order property lets you rearrange them visually. Items with lower order values come first. The default is 0.

⚠️
Accessibility warning order only changes visual order — screen readers and keyboard navigation still follow the HTML source order. Use order sparingly and never let visual order differ dramatically from the logical reading order.

align-self

align-self overrides the container's align-items for a single item. It takes all the same values: stretch, flex-start, flex-end, center, and baseline. This is perfect when one item needs to be positioned differently from the rest.

CSS
Try it →
.container {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 150px;
  background: #f8fafc;
  padding: 12px;
  border-radius: 8px;
}

.item {
  padding: 16px;
  background: #6366f1;
  color: white;
  border-radius: 6px;
}

/* This one breaks away from the group */
.special {
  align-self: flex-end;
  background: #ec4899;
}

📏 The gap Property

Before gap, developers used margins on flex items to create spacing — which caused edge-alignment issues and required workarounds. The gap property (applied to the container) adds space between items only, never on the outer edges.

CSS
Try it →
/* gap adds space between items only */
.card-row {
  display: flex;
  gap: 20px;
}

/* Different row and column gaps */
.grid-like {
  display: flex;
  flex-wrap: wrap;
  row-gap: 24px;
  column-gap: 16px;
}

.card {
  flex: 1 1 200px;
  padding: 20px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
}
💡
gap vs. margin gap only adds space between items — never on the outer edges. With margins, the first and last items would also have unwanted space on the container edges. gap is cleaner, more predictable, and the modern best practice.

🏗️ Real-World Flexbox Patterns

Let's combine everything you've learned into practical patterns you'll use on real websites. These are production-ready starting points.

Pattern 1: Responsive Navbar

A classic navbar: logo on the left, navigation links on the right, vertically centered.

CSS
Try it →
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 24px;
  background: #0f172a;
  color: white;
}

.logo {
  font-size: 1.5rem;
  font-weight: 700;
}

.nav-links {
  display: flex;
  gap: 24px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-links a {
  color: #94a3b8;
  text-decoration: none;
  transition: color 0.2s;
}

.nav-links a:hover {
  color: white;
}

Pattern 2: Card Row with Equal Heights

Three cards in a row that wrap on small screens. Each card stretches to match the tallest one.

CSS
Try it →
.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  flex: 1 1 280px;
  padding: 24px;
  background: white;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

.card h3 {
  margin: 0 0 12px;
}

.card p {
  color: #64748b;
  line-height: 1.6;
}
💡
The flex: 1 1 280px trick This means: "start at 280px, grow to fill space, and shrink if needed." When the container is wide, all three cards fit in a row. When it narrows, cards wrap to new lines. This single line replaces media queries for many simple responsive layouts.

Pattern 3: Perfect Centering

The single most common Flexbox pattern. Center any element both horizontally and vertically in just three lines.

CSS
Try it →
/* The holy grail of CSS centering */
.center-everything {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 300px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  border-radius: 12px;
}

.centered-box {
  background: white;
  padding: 32px 48px;
  border-radius: 12px;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}

Pattern 4: Sidebar Layout

A fixed-width sidebar with a flexible main content area. This is the layout pattern used on this very course page.

CSS
Try it →
.page-layout {
  display: flex;
  min-height: 400px;
}

.sidebar {
  flex: 0 0 250px;
  background: #1e293b;
  color: white;
  padding: 24px;
}

.main-content {
  flex: 1;
  padding: 24px;
  background: #f8fafc;
}

.sidebar ul {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sidebar a {
  color: #94a3b8;
  text-decoration: none;
  padding: 8px 12px;
  border-radius: 6px;
  transition: background 0.2s;
}

.sidebar a:hover {
  background: rgba(255,255,255,0.1);
}

Pattern 5: Footer with Columns

A footer divided into equal-width columns that wrap on small screens.

CSS
Try it →
.footer {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  padding: 48px 24px;
  background: #0f172a;
  color: #cbd5e1;
}

.footer-column {
  flex: 1 1 200px;
}

.footer-column h4 {
  color: white;
  margin-bottom: 16px;
}

.footer-column ul {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

Pattern 6: Pushing Items with Auto Margins

A powerful trick: margin-left: auto (or margin-right: auto) on a flex item pushes it as far as possible in that direction. This is perfect for placing a single element on the opposite side of a flex row.

CSS
Try it →
.header {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 24px;
  background: #f1f5f9;
  border-radius: 8px;
}

/* Push logout button to the far right */
.logout {
  margin-left: auto;
  padding: 8px 16px;
  background: #ef4444;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

✏️ Practice: Flexbox Layout

Test your understanding of flex containers, items, alignment, and real-world patterns.

Exercise 1: Center a Box

Write CSS for a .container that centers a child element both horizontally and vertically. The container should be at least 300px tall.

Reveal Solution

.container { display: flex; justify-content: center; align-items: center; min-height: 300px; }

💡 justify-content: center centers on the main (horizontal) axis. align-items: center centers on the cross (vertical) axis. Together, they perfectly center any child element.

Exercise 2: Navbar Layout

You have a <nav> with a .logo div and a <ul class="links">. Write CSS to: (1) place the logo on the left and the links on the right, (2) vertically center both, (3) add 24px gap between the link items.

Reveal Solution

nav { display: flex; justify-content: space-between; align-items: center; } — places logo at start, links at end, vertically centered.

.links { display: flex; gap: 24px; list-style: none; } — the <ul> is also a flex container. gap creates even spacing between items. list-style: none removes the bullets.

Exercise 3: Responsive Card Grid

Create a .card-grid class where cards: (1) wrap onto new rows, (2) have a minimum width of 250px, (3) grow to fill available space equally, (4) have 20px gap between cards.

Reveal Solution

.card-grid { display: flex; flex-wrap: wrap; gap: 20px; }

.card-grid > * { flex: 1 1 250px; }flex: 1 1 250px means "start at 250px minimum, grow equally, and shrink if needed." This creates a responsive grid without any media queries.

Exercise 4: Sidebar + Main Layout

Create a two-column layout where: (1) the sidebar is exactly 280px wide and never grows or shrinks, (2) the main content fills all remaining space, (3) both sections fill the full height.

Reveal Solution

.layout { display: flex; min-height: 100vh; }min-height: 100vh makes it fill the full viewport. align-items: stretch (the default) ensures both children fill the height.

.sidebar { flex: 0 0 280px; } — fixed at 280px, no growing, no shrinking.

.main { flex: 1; } — takes all remaining space.

📋 Module Summary

📦
Flex Container

display: flex activates Flexbox. Direct children become flex items. flex-direction sets the main axis (row or column). flex-wrap: wrap allows multi-line layouts.

↔️
Main Axis

justify-content distributes items along the main axis. Key values: space-between (edges), center, space-evenly (equal gaps).

↕️
Cross Axis

align-items positions items on the cross axis. stretch (default) makes equal heights. center for vertical centering. align-content positions wrapped lines.

🧩
Flex Items

flex: 1 to fill space. flex: 0 0 250px for fixed width. flex: 1 1 280px for responsive cards. align-self overrides alignment for one item.

📏
Gap & Spacing

gap adds space between items only (not edges). Use row-gap and column-gap for different spacing. margin-left: auto pushes items to the opposite side.

🏗️
Patterns

Navbar: space-between + center. Perfect centering: justify-content: center; align-items: center. Sidebar: fixed + flex: 1. Cards: flex: 1 1 280px + wrap.

Next Module →

Module 8: Layout: CSS Grid

Master two-dimensional layouts. Grid templates, named areas, auto-fit, and the full power of CSS Grid for complex page designs.