Flexbox Practice Layouts
Build 8 real-world layout patterns using Flexbox — from navbars to cards to the Holy Grail.
1. Introduction
The best way to learn Flexbox is to build real patterns you will encounter on every project. This lesson is a pattern library — 8 common layout patterns, each with complete HTML and CSS, explained step by step.
Patterns covered:
- Navigation bar (logo left, links right)
- Hero section (centred content)
- Equal-height card row
- Card with footer pushed to bottom
- Sidebar layout (Holy Grail)
- Media object (image + text)
- Responsive wrapping grid
- Stacked form layout
2. Quick Reference: Pattern Recipes
Pattern 1: Navigation Bar
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 64px;
}
.navbar__nav {
display: flex;
gap: 8px;
list-style: none;
}
Pattern 2: Perfect Centre
.centred {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
Pattern 3: Equal-Height Cards
.card-row {
display: flex;
gap: 16px;
align-items: stretch; /* default — cards match tallest height */
}
.card-row .card { flex: 1; }
Pattern 4: Card Footer Push
.card {
display: flex;
flex-direction: column;
}
.card__body { flex: 1; } /* grows to push footer down */
.card__footer { margin-top: auto; } /* alternative: auto margin */
Pattern 5: Holy Grail Layout
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.page__middle {
display: flex;
flex: 1;
}
.sidebar-left { flex: 0 0 250px; }
.main-content { flex: 1; }
.sidebar-right { flex: 0 0 200px; }
Pattern 6: Media Object
.media {
display: flex;
gap: 16px;
align-items: flex-start;
}
.media__image { flex-shrink: 0; width: 80px; }
.media__body { flex: 1; min-width: 0; }
Pattern 7: Responsive Wrapping Grid
.grid {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.grid__item { flex: 1 1 280px; max-width: 100%; }
Pattern 8: Stacked Form
.form-row {
display: flex;
gap: 16px;
align-items: flex-end; /* align label-input pairs at bottom */
}
.form-field { flex: 1; display: flex; flex-direction: column; gap: 6px; }
3. Real World Example
These 8 patterns appear on almost every website:
- Pattern 1 (navbar) — GitHub top nav, Stripe header, every SaaS product
- Pattern 2 (centre) — Login pages, error 404 pages, coming-soon pages
- Pattern 4 (footer push) — Pricing cards where the "Buy" button must align at the bottom across all cards
- Pattern 5 (Holy Grail) — Admin dashboards, documentation sites, email clients
- Pattern 6 (media object) — Social media posts, comment threads, notification items
- Pattern 7 (responsive grid) — Blog post listings, product catalogs, team pages
4. Full Code Example
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flexbox Patterns</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Pattern 1: Navbar -->
<nav class="navbar">
<a class="navbar__brand" href="#">MyApp</a>
<ul class="navbar__nav">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Blog</a></li>
</ul>
<a class="btn btn--primary" href="#">Sign Up</a>
</nav>
<!-- Pattern 4: Equal-height card row with footer push -->
<section class="section">
<div class="card-row">
<div class="card">
<div class="card__body">
<h3>Basic Plan</h3>
<p>Short description.</p>
</div>
<div class="card__footer">
<button class="btn">Get Started</button>
</div>
</div>
<div class="card">
<div class="card__body">
<h3>Pro Plan</h3>
<p>This card has much more description text so it is taller than the others.</p>
</div>
<div class="card__footer">
<button class="btn btn--primary">Get Started</button>
</div>
</div>
<div class="card">
<div class="card__body">
<h3>Enterprise</h3>
<p>Short.</p>
</div>
<div class="card__footer">
<button class="btn">Contact Us</button>
</div>
</div>
</div>
</section>
</body>
</html>
CSS (patterns.css):
/* Reset */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
body { font-family: 'Inter', sans-serif; background: #f8fafc; }
/* ===== PATTERN 1: NAVBAR ===== */
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32px;
height: 64px;
background: #1e293b;
color: white;
position: fixed;
top: 0; left: 0; right: 0;
z-index: 100;
}
.navbar__brand {
font-size: 1.25rem;
font-weight: 700;
color: white;
text-decoration: none;
}
.navbar__nav {
display: flex;
gap: 4px;
list-style: none;
}
.navbar__nav a {
color: #94a3b8;
text-decoration: none;
padding: 8px 12px;
border-radius: 6px;
transition: all 0.2s;
}
.navbar__nav a:hover { color: white; background: rgba(255,255,255,0.1); }
/* ===== PATTERN 4: EQUAL-HEIGHT CARDS + FOOTER PUSH ===== */
.section { padding: 80px 32px 32px; }
.card-row {
display: flex;
gap: 24px;
align-items: stretch; /* equal heights */
}
.card {
flex: 1;
display: flex;
flex-direction: column; /* stack body and footer vertically */
background: white;
border-radius: 12px;
border: 1px solid #e2e8f0;
overflow: hidden;
}
.card__body {
flex: 1; /* grow to push footer down */
padding: 24px;
}
.card__body h3 {
font-size: 1.25rem;
margin-bottom: 12px;
}
.card__footer {
padding: 16px 24px;
border-top: 1px solid #f1f5f9;
background: #fafafa;
}
/* ===== BUTTONS ===== */
.btn {
display: inline-block;
padding: 10px 20px;
border-radius: 6px;
font-size: 0.875rem;
font-weight: 600;
cursor: pointer;
border: 1px solid #e2e8f0;
background: white;
width: 100%;
text-align: center;
transition: all 0.2s;
}
.btn--primary {
background: #2563eb;
color: white;
border-color: #2563eb;
}
.btn--primary:hover { background: #1d4ed8; }
5. Code Breakdown
- Navbar:
justify-content: space-between - Pushes the brand to the left edge and the sign-up button to the right, with the nav links in the middle. The three children act as anchors at start, middle, and end of the flex row.
- Card:
display: flex; flex-direction: column - Each card is itself a flex container in column direction. This stacks the header, body, and footer vertically. The body then uses
flex: 1to grow and fill remaining space — pushing the footer to the bottom regardless of content length. align-items: stretchon card-row- The default! All cards in the row are stretched to match the tallest card's height. This is why the "Basic" and "Enterprise" cards (shorter content) still match the "Pro" card's height — creating equal-height cards.
card__footerat the bottom- Because the card is a flex column with the body set to
flex: 1, the footer is always pushed to the bottom. All three "Get Started" buttons will line up perfectly on the same horizontal line, even though the cards have different content lengths.
6. Common Mistakes
- Forgetting to make the card a flex container for the footer-push pattern. The card must have
display: flex; flex-direction: columnAND the body must haveflex: 1. Missing either one breaks the pattern. - Using
height: 100%instead offlex: 1for the Holy Grail. Percentage heights need explicit parent heights. Flex approach is more flexible and works correctly without explicit heights. - Not setting
min-width: 0on flex items with text content. Long words or URLs can cause items to overflow the flex container. - Not testing with wrapping content. Always test your flex layouts with both short and long content to ensure they hold up.
7. Best Practices
- Use the card footer-push pattern for any card that has a button — all buttons align on the same line.
- Use the Holy Grail for any sidebar layout — reliable and responsive.
- Use the media object pattern for comment lists, notification items, and any image + text combos.
- Use wrapping grid with
flex: 1 1 Xpxfor responsive image galleries and card grids without media queries. - Nest flex containers freely — the navbar items are flex, and each navbar nav is also flex. Multiple levels of flexbox are normal and expected.
8. Practice Exercise
Build each of the 8 patterns from scratch without looking at the code examples. For each pattern:
- Write the HTML structure
- Write the CSS from memory
- Compare with the example above
Focus on: Pattern 1 (navbar), Pattern 2 (centred content), Pattern 4 (card footer push), Pattern 6 (media object). These are the most used.
9. Assignment — Flexbox Capstone
Build a complete product page using only Flexbox for all layout (no float, no grid):
- Fixed navbar — Pattern 1
- Hero section — Pattern 2 (centred), with a horizontal button group (Pattern 8 variant)
- Features section — three cards (Pattern 3/4) with equal heights and bottom-aligned CTAs
- Testimonials section — media object pattern (Pattern 6) for quote + avatar + name
- Pricing section — three pricing cards with footer push buttons (Pattern 4)
- Footer — multi-column layout with wrapping (Pattern 5 variant)
- Responsive: on mobile everything stacks in a column
10. Interview Questions
Q1: How do you create a navigation bar with a logo on the left and links on the right?
Answer: Apply display: flex; justify-content: space-between; align-items: center; to the nav element. The logo and links group are the two flex items — space-between pushes them to opposite ends. The links group is itself a flex container with display: flex; gap: 8px;.
Q2: How do you make all cards in a row the same height?
Answer: The default align-items: stretch on the flex container makes all flex items stretch to match the tallest item's height. No additional CSS is needed — just make sure the cards are direct flex items with no conflicting height settings.
Q3: How do you push a card footer to the bottom regardless of content length?
Answer: Make the card a flex column: display: flex; flex-direction: column;. Give the card body flex: 1 to grow and fill available space. The footer, having no flex-grow, stays at the bottom. Alternatively, apply margin-top: auto to the footer.
Q4: What is the "media object" pattern?
Answer: A layout with a fixed-size image/icon on one side and flexible text content on the other. Implementation: a flex container with align-items: flex-start; gap: 16px;, the image with flex-shrink: 0; (fixed width), and the text with flex: 1; min-width: 0;. Used for social posts, notifications, comment lists.
Q5: When would you use CSS Grid instead of Flexbox?
Answer: Use Flexbox for one-dimensional layouts (either a row or a column). Use CSS Grid for two-dimensional layouts where you need to control both rows and columns simultaneously — like a magazine layout, a complex dashboard, or a calendar. In practice, many layouts use both: Grid for page structure, Flexbox for component internals.
11. Additional Resources
- Flexbox Froggy — flexboxfroggy.com
- CSS-Tricks — Flexbox Guide (search "css-tricks complete guide flexbox")
- Every Layout by Andy Bell — every-layout.dev
- Solved by Flexbox — philipwalton.github.io/solved-by-flexbox
- MDN Flexbox (search "MDN CSS flexbox layout")