📐 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.
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-directionandflex-wrap - Align items along the main axis with
justify-content - Align items along the cross axis with
align-itemsandalign-content - Size flex items with
flex-grow,flex-shrink, andflex-basis - Use the
gapproperty 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.
/* The parent becomes a flex container */ .container { display: flex; } /* Children automatically become flex items */ .item { padding: 20px; background: #3b82f6; color: white; border-radius: 8px; }
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
row — Items flow left → right (default). Main axis is horizontal.
row-reverse — Items flow right → left. Main axis is horizontal, reversed.
column — Items flow top → bottom. Main axis is vertical.
column-reverse — Items flow bottom → top. Main axis is vertical, reversed.
/* 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.
/* 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
nowrap — All items stay on one line (default). Items shrink if needed.
wrap — Items wrap onto new lines when the container runs out of space.
wrap-reverse — Items wrap onto new lines above (or to the left in column mode).
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
flex-start — Items packed to the start (default).
flex-end — Items packed to the end.
center — Items centered along the main axis.
space-between — First item at start, last at end, equal space between each item.
space-around — Equal space around each item. Items have half-size spaces on the edges.
space-evenly — Exactly equal space between and around all items.
/* 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
stretch — Items stretch to fill the container height (default).
flex-start — Items aligned to the top (start of cross axis).
flex-end — Items aligned to the bottom (end of cross axis).
center — Items centered vertically.
baseline — Items aligned by their text baseline — useful when items have different font sizes.
/* 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 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.
.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
flex: 1 — Same as flex: 1 1 0%. Item grows and shrinks equally, starting from zero width. All items with flex: 1 share space equally.
flex: auto — Same as flex: 1 1 auto. Like flex: 1 but starts from the item's natural size before distributing space.
flex: none — Same as flex: 0 0 auto. Item is completely inflexible — no growing, no shrinking.
flex: 0 0 250px — Fixed at 250px. Won't grow or shrink. Common for fixed sidebars.
.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.
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.
.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.
/* 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 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.
.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.
.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; }
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.
/* 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.
.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.
.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.
.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
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.
justify-content distributes items along the main axis. Key values: space-between (edges), center, space-evenly (equal gaps).
align-items positions items on the cross axis. stretch (default) makes equal heights. center for vertical centering. align-content positions wrapped lines.
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 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.
Navbar: space-between + center. Perfect centering: justify-content: center; align-items: center. Sidebar: fixed + flex: 1. Cards: flex: 1 1 280px + wrap.