Flexbox truly shines when building responsive layouts โ components that reflow gracefully from desktop to mobile without excessive media queries. In this lesson you will combine everything from this chapter โ flex-wrap, flex-basis, alignment, and the auto-margin trick โ into fully responsive real-world layouts: a responsive navigation bar, a card grid, and a full-page dashboard shell.
Responsive Flexbox Strategies
| Strategy | How | When to Use |
|---|---|---|
| Auto-wrap grid | flex-wrap: wrap + flex: 1 1 Npx on items |
Cards, tiles, tags โ consistent items |
| Axis flip | Change flex-direction at breakpoint |
Side-by-side to stacked on mobile |
| Conditional flex | display: flex only above a breakpoint |
Horizontal nav that stacks on mobile |
| Gap scaling | Change gap value at breakpoints |
Tighter spacing on small screens |
| Order swap | Use order to move hero image above text on mobile |
Mobile-first content prioritisation |
Responsive Navigation Approaches
| Approach | Desktop | Mobile | JS Needed? |
|---|---|---|---|
| Flex hide/show | display: flex nav links |
display: none + hamburger shown |
Yes โ toggle class |
| Flex wrap | Single-row nav | Nav links wrap to second row | No |
| Direction flip | flex-direction: row |
flex-direction: column |
No |
Breakpoint Values for Flexbox
| Breakpoint Name | Min-width | Typical Change |
|---|---|---|
| sm (small) | 640px | Single column to two columns |
| md (medium) | 768px | Show sidebar; two to three columns |
| lg (large) | 1024px | Full horizontal navigation |
| xl (extra large) | 1280px | Wider containers; more columns |
@media (min-width: Npx) to progressively enhance for larger screens. This results in less media query code, faster mobile paint, and more maintainable stylesheets.display: flex; flex-wrap: wrap; on the container and flex: 1 1 280px; max-width: 400px; on cards. The browser does the column math automatically based on available width.flex-direction to flip from row to column on mobile, remember that justify-content and align-items also flip their axes. Always test your alignment properties at every breakpoint when changing direction.Basic Example โ Fully Responsive Dashboard
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Flexbox Dashboard</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; background: #f1f5f9; min-height: 100vh; }
/* โโ Navigation โโ */
.nav {
background: #1e293b;
padding: 0 24px;
display: flex;
align-items: center;
flex-wrap: wrap; /* allows links to wrap on small screens */
gap: 0;
min-height: 56px;
}
.nav-brand {
color: white; font-weight: 700; font-size: 1rem;
padding: 14px 0; margin-right: auto; /* pushes links to the right */
}
.nav-links {
display: flex; flex-wrap: wrap; list-style: none; gap: 0;
}
.nav-links a {
display: block; padding: 16px 14px;
color: #94a3b8; text-decoration: none; font-size: 0.875rem;
transition: color 0.15s;
}
.nav-links a:hover { color: white; }
.nav-links .active a { color: #818cf8; border-bottom: 2px solid #818cf8; }
/* โโ Stats row โ wraps to single column on mobile โโ */
.stats-row {
display: flex;
flex-wrap: wrap;
gap: 16px;
padding: 24px;
}
.stat-card {
flex: 1 1 180px; /* wraps: 4 on desktop, 2 on tablet, 1 on mobile */
background: white;
border-radius: 12px;
padding: 20px;
border: 1px solid #e2e8f0;
}
.stat-label { font-size: 0.75rem; font-weight: 600; text-transform: uppercase;
letter-spacing: 0.06em; color: #64748b; margin-bottom: 8px; }
.stat-value { font-size: 1.75rem; font-weight: 800; color: #0f172a; }
.stat-delta { font-size: 0.8rem; color: #10b981; font-weight: 600; margin-top: 4px; }
/* โโ Main content area โ sidebar stacks on mobile โโ */
.content-area {
display: flex;
flex-wrap: wrap;
gap: 24px;
padding: 0 24px 24px;
}
.main-panel {
flex: 1 1 400px; /* grows to fill; wraps below sidebar on mobile */
background: white;
border-radius: 12px;
border: 1px solid #e2e8f0;
padding: 24px;
}
.side-panel {
flex: 0 1 280px; /* shrinks but doesn't grow beyond 280px */
min-width: 240px;
background: white;
border-radius: 12px;
border: 1px solid #e2e8f0;
padding: 24px;
}
.panel-title {
font-size: 0.875rem; font-weight: 700; color: #0f172a;
margin: 0 0 16px; padding-bottom: 12px;
border-bottom: 1px solid #f1f5f9;
}
/* โโ Activity list โโ */
.activity-item {
display: flex; gap: 12px; align-items: flex-start;
padding: 10px 0; border-bottom: 1px solid #f8fafc;
font-size: 0.875rem;
}
.activity-icon {
width: 32px; height: 32px; border-radius: 8px; flex-shrink: 0;
display: flex; align-items: center; justify-content: center; font-size: 0.9rem;
}
.activity-body { flex: 1; min-width: 0; }
.activity-body strong { display: block; color: #0f172a; margin-bottom: 2px;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.activity-body span { color: #94a3b8; font-size: 0.8rem; }
.activity-time { color: #94a3b8; font-size: 0.75rem; white-space: nowrap; flex-shrink: 0; }
</style>
</head>
<body>
<nav class="nav">
<span class="nav-brand">Dashboard</span>
<ul class="nav-links">
<li class="active"><a href="#">Overview</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Settings</a></li>
</ul>
</nav>
<div class="stats-row">
<div class="stat-card">
<div class="stat-label">Total Revenue</div>
<div class="stat-value">$48,295</div>
<div class="stat-delta">+12.5% this month</div>
</div>
<div class="stat-card">
<div class="stat-label">Active Users</div>
<div class="stat-value">3,847</div>
<div class="stat-delta">+8.1% this week</div>
</div>
<div class="stat-card">
<div class="stat-label">New Orders</div>
<div class="stat-value">294</div>
<div class="stat-delta">+3.2% today</div>
</div>
<div class="stat-card">
<div class="stat-label">Conversion</div>
<div class="stat-value">5.4%</div>
<div class="stat-delta">+0.8% this week</div>
</div>
</div>
<div class="content-area">
<div class="main-panel">
<h2 class="panel-title">Recent Activity</h2>
<div class="activity-item">
<div class="activity-icon" style="background:#ede9fe">🛒</div>
<div class="activity-body"><strong>New order #1042 received</strong><span>Customer: Sarah K.</span></div>
<div class="activity-time">2m ago</div>
</div>
<div class="activity-item">
<div class="activity-icon" style="background:#d1fae5">✓</div>
<div class="activity-body"><strong>Order #1039 shipped</strong><span>Tracking: FX-29471</span></div>
<div class="activity-time">18m ago</div>
</div>
<div class="activity-item">
<div class="activity-icon" style="background:#fee2e2">📢</div>
<div class="activity-body"><strong>Low stock alert: SKU-448</strong><span>Only 3 units remaining</span></div>
<div class="activity-time">1h ago</div>
</div>
</div>
<div class="side-panel">
<h2 class="panel-title">Top Products</h2>
<div style="display:flex;flex-direction:column;gap:12px;font-size:0.875rem;">
<div style="display:flex;justify-content:space-between;align-items:center;"><span style="color:#334155">Widget Pro</span><span style="font-weight:700;color:#4f46e5">$12,400</span></div>
<div style="display:flex;justify-content:space-between;align-items:center;"><span style="color:#334155">Gadget Plus</span><span style="font-weight:700;color:#4f46e5">$9,200</span></div>
<div style="display:flex;justify-content:space-between;align-items:center;"><span style="color:#334155">Starter Kit</span><span style="font-weight:700;color:#4f46e5">$7,650</span></div>
</div>
</div>
</div>
</body>
</html>
How It Works
Step 1 โ Nav Uses margin-right: auto to Push Links Right
The brand has margin-right: auto which absorbs all surplus horizontal space to its right โ pushing the nav-links group to the far right of the bar. The nav also has flex-wrap: wrap so links drop to a second row on very small screens.
Step 2 โ Stats Row Auto-Wraps to Fewer Columns
Each stat card has flex: 1 1 180px. On a 1100px desktop, four cards comfortably fit in a row (4 ร 180 + 3 ร 16 = 768px). On a 480px mobile, only two fit per row (2 ร 180 + 1 ร 16 = 376px), so the other two wrap โ all without a single media query.
Step 3 โ Content Area Flips from Side-by-Side to Stacked
The main panel has flex: 1 1 400px and the side panel has flex: 0 1 280px; min-width: 240px. On wide screens they sit side by side. When the viewport narrows below about 680px, both wrap to full-width stacked blocks โ again, no media queries needed.
Step 4 โ Activity Items Use the Media Object Pattern
Each activity row is a flex container with an icon, a body (flex: 1; min-width: 0), and a timestamp (flex-shrink: 0). The body has text-overflow: ellipsis with min-width: 0 โ the essential fix for flex items that contain truncated text.
Step 5 โ min-width: 0 Enables Text Truncation in Flex Items
Without min-width: 0, a flex item’s minimum size is its content width โ it will not shrink below it, even if that causes overflow. Setting min-width: 0 allows the item to shrink below its content width so that text-overflow: ellipsis can trigger.
Real-World Example: Responsive Article Layout
/* article-layout.css โ mobile-first */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; background: #f8fafc; color: #1e293b; }
/* Wrapper */
.article-layout {
display: flex;
flex-direction: column; /* mobile: stacked */
gap: 24px;
padding: 24px 16px;
max-width: 1100px;
margin-inline: auto;
}
/* Desktop: side by side */
@media (min-width: 768px) {
.article-layout {
flex-direction: row;
align-items: flex-start;
padding: 40px 24px;
}
}
/* Main article */
.article-content {
flex: 1;
min-width: 0;
background: white;
border-radius: 12px;
padding: 32px;
border: 1px solid #e2e8f0;
}
/* Sidebar โ full-width on mobile, fixed 280px on desktop */
.article-sidebar {
flex: 0 0 100%; /* full-width mobile */
background: white;
border-radius: 12px;
padding: 24px;
border: 1px solid #e2e8f0;
}
@media (min-width: 768px) {
.article-sidebar { flex: 0 0 280px; } /* fixed sidebar on desktop */
}
/* Related posts โ wrapping grid */
.related-posts {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 16px;
}
.related-post {
flex: 1 1 200px;
font-size: 0.8rem;
color: #4f46e5;
text-decoration: none;
padding: 10px 12px;
background: #f1f5f9;
border-radius: 8px;
border: 1px solid #e2e8f0;
line-height: 1.4;
}
.related-post:hover { background: #ede9fe; border-color: #c4b5fd; }
Common Mistakes
Mistake 1 โ Forgetting min-width: 0 on flex items with truncated text
โ Wrong โ text overflows because flex item doesn’t shrink below content width:
.item { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* text-overflow never triggers โ item won't shrink */
โ Correct โ min-width: 0 allows shrinking below content width:
.item { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
Mistake 2 โ Applying justify-content: space-between with flex-wrap
โ Wrong โ last partial row items spread awkwardly with space-between:
.grid { display: flex; flex-wrap: wrap; justify-content: space-between; }
/* 5 items in rows of 3: last 2 items spread to left and right edges */
โ Correct โ use gap for consistent spacing; let items align to the start:
.grid { display: flex; flex-wrap: wrap; gap: 16px; }
Mistake 3 โ Changing flex-direction without updating alignment properties
โ Wrong โ alignment breaks after direction flip because axes have swapped:
.row { display: flex; flex-direction: row; justify-content: center; align-items: center; }
@media (max-width: 640px) {
.row { flex-direction: column; }
/* justify-content: center now centers VERTICALLY โ was horizontal */
}
โ Correct โ explicitly reset alignment at the breakpoint:
@media (max-width: 640px) {
.row { flex-direction: column; align-items: center; justify-content: flex-start; }
}
Quick Reference
| Responsive Pattern | CSS | Notes |
|---|---|---|
| Auto-wrap grid | flex-wrap: wrap; flex: 1 1 260px; |
No media queries needed |
| Direction flip | flex-direction: column then row at breakpoint |
Re-check alignment properties after flip |
| Full to fixed sidebar | flex: 0 0 100% mobile โ flex: 0 0 280px desktop |
Mobile-first with min-width breakpoint |
| Text truncation | flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; |
min-width: 0 is the critical addition |
| Push to edge | margin-left: auto or margin-right: auto |
No wrapper needed |