A Complete Guide to CSS Flexbox
Master the Flexible Box Layout Module to create responsive and flexible web layouts.
Master the Flexible Box Layout Module to create responsive and flexible web layouts.

Introduction: Have you ever struggled with centering elements or creating responsive layouts in CSS? If so, you're not alone. This is exactly where Flexbox comes to the rescue, offering an elegant solution to common layout challenges that have plagued developers for years.
Flexbox, or the Flexible Box Layout Module, is a powerful CSS layout system that makes it incredibly easy to design flexible and responsive layouts without relying on floats or positioning hacks. Whether you're building a navigation bar, a card grid, or simply trying to center that stubborn div, Flexbox provides the tools you need to accomplish these tasks efficiently and elegantly.
Before Flexbox, creating layouts in CSS was often a frustrating experience. Developers had to rely on floats, positioning, and display properties that weren't originally designed for complex layouts. These methods were often unintuitive and required numerous workarounds to achieve even basic layout patterns.
Flexbox fundamentally changed the game by introducing a layout system specifically designed for distributing space and aligning items within a container. It excels at creating one-dimensional layouts, making it perfect for organizing items in rows or columns. The flexible sizing mechanism allows items to grow or shrink to fit available space automatically.
One of the most celebrated features of Flexbox is its powerful alignment capabilities. Tasks that previously required complex CSS hacks, like vertical centering, can now be accomplished with just a couple of properties. Additionally, Flexbox layouts are responsive by nature, adapting beautifully to different screen sizes without extensive media queries.
Every Flexbox layout starts with a flex container. Think of it as the parent element that holds all your flex items (children).
Here's how you create one:
.container {
display: flex;
}
Or, if you want an inline flex container:
.container {
display: inline-flex;
}
Once you set display flex on an element, all of its direct children automatically become flex items. This means you don't need to add any additional classes or properties to the child elements for them to participate in the flex layout.
Important considerations:
The flex-direction property is your compass for Flexbox. It determines which way your items flow, essentially setting the main axis for your layout.
Default syntax:
.container {
flex-direction: row; /* Default */
}
Let's explore each option in detail:
.container {
flex-direction: row;
}
Items flow from left to right, just like reading a book in English. This makes it perfect for horizontal navigation bars and other left-to-right content arrangements.
Best for:
.container {
flex-direction: row-reverse;
}
Items flow from right to left. Useful when you need to reverse the visual order without changing your HTML.
Use cases:
.container {
flex-direction: column;
}
Items stack from top to bottom. This is particularly useful for vertical navigation menus, mobile layouts, and any scenario where you need a vertical arrangement of elements.
Best for:
.container {
flex-direction: column-reverse;
}
Items stack from bottom to top. Less common, but handy for specific design needs like chat interfaces or reversed timelines.
What happens when you have more items than can fit in one line? That's where the flex-wrap property comes in. By default, flex items will try to fit into one line, which can cause overflow issues. The flex-wrap property gives you control over whether items should wrap to multiple lines and in which direction.
.container {
flex-wrap: nowrap; /* Default */
}
All items stay in one line, even if they overflow the container.
.container {
flex-wrap: nowrap;
}
Items wrap to the next line when there's no more space.
.container {
flex-wrap: wrap;
}
Perfect for:
Items wrap to new lines above the current line.
.container {
flex-wrap: wrap-reverse;
}
Consider a real-world example of building a responsive image gallery. With flex-wrap set to wrap, images automatically flow to the next row when the screen gets smaller. This creates a naturally responsive layout without the need for complex media query calculations or JavaScript interventions.
.gallery {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.gallery-item {
flex: 1 1 250px; /* Minimum width of 250px */
}
The justify-content property controls how items are distributed along the main axis of your flex container. This is one of the most powerful and frequently used features of Flexbox, allowing you to create sophisticated alignment patterns with minimal code.
.container {
display: flex;
justify-content: flex-start; /* Default */
}
justify-content: flex-start;
Items bunch up at the start. Think left side for row, top for column.
Use cases:
justify-content: flex-end;
Items bunch up at the end. This is perfect for creating right-aligned navigation elements or placing content at the end of a container.
Use cases:
justify-content: center;
The holy grail of centering! Items gather in the middle.
Use cases:
justify-content: space-between;
Items spread out with equal space between them, while the first item aligns to the start and the last item aligns to the end. This creates a balanced distribution that works exceptionally well for navigation bars and header layouts.
Use cases:
justify-content: space-around;
Items have equal space around them. Each item gets equal margin on both sides.
Use cases:
justify-content: space-evenly;
All spaces are exactly equal, including the edges. The most evenly distributed option.
Use cases:
/* Navigation with logo and menu items */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
/* Centered hero content */
.hero {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Evenly spaced feature cards */
.features {
display: flex;
justify-content: space-evenly;
gap: 2rem;
}
While justify-content works on the main axis, align-items handles the cross axis (perpendicular to the main axis). This property is essential for vertical alignment in row layouts and horizontal alignment in column layouts.
.container {
display: flex;
align-items: stretch; /* Default */
}
align-items: stretch;
Items stretch to fill the container height. This is particularly useful for creating equal-height cards or columns, ensuring a consistent appearance regardless of content length.
Best for:
align-items: flex-start;
Items align to the start of the cross axis (top for row, left for column).
Use cases:
align-items: flex-end;
Items align to the end of the cross axis (bottom for row, right for column).
Use cases:
align-items: center;
Items center along the cross axis. When combined with justify-content center, this creates perfect horizontal and vertical centering, solving one of CSS's most notorious challenges with remarkable simplicity.
Perfect for:
align-items: baseline;
Items align based on their text baseline. Great for text-heavy layouts.
Use cases:
/* Card with centered icon and text */
.feature-card {
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem;
text-align: center;
}
/* Navbar with vertically centered items */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
}
When you have multiple lines of flex items (with flex-wrap: wrap), align-content controls how those lines are distributed along the cross axis. This property has no effect when there's only one line of flex items.
.container {
display: flex;
flex-wrap: wrap;
align-content: stretch; /* Default */
}
The values are similar to justify-content:
flex-start: Lines packed to the startflex-end: Lines packed to the endcenter: Lines packed to the centerspace-between: Lines evenly distributedspace-around: Lines evenly distributed with space aroundstretch: Lines stretch to fill the containerThis property is particularly useful for:
.tag-container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
gap: 0.5rem;
max-height: 200px;
overflow-y: auto;
}
While the previous properties are applied to the flex container, there's an equally powerful set of properties that can be applied to individual flex items. These properties give you fine-grained control over how specific items behave within the flex layout.
Defines how much an item should grow relative to other items when there's extra space available.
Syntax:
.item {
flex-grow: 0; /* Default - don't grow */
}
Common values:
.item-1 {
flex-grow: 0; /* Won't grow */
}
.item-2 {
flex-grow: 1; /* Will grow to fill available space */
}
.item-3 {
flex-grow: 2; /* Will grow twice as much as item-2 */
}
Use cases:
Defines how much an item should shrink relative to other items when there's not enough space.
Syntax:
.item {
flex-shrink: 1; /* Default - can shrink */
}
Examples:
.logo {
flex-shrink: 0; /* Never shrink the logo */
}
.nav-item {
flex-shrink: 1; /* Allow navigation items to shrink */
}
Use cases:
Sets the initial size of an item before growing or shrinking occurs.
Syntax:
.item {
flex-basis: auto; /* Default - based on content */
}
Examples:
.sidebar {
flex-basis: 250px; /* Start at 250px */
}
.main-content {
flex-basis: 0; /* Start at 0, then grow */
}
.footer-section {
flex-basis: 33.333%; /* Start at 1/3 of container */
}
Use cases:
You can combine all three properties (grow, shrink, and basis) into a single shorthand property. This is the recommended way to set flex properties.
Syntax:
.item {
flex: [grow] [shrink] [basis];
}
Common patterns:
/* Don't grow or shrink, use content size */
.item-fixed {
flex: 0 0 auto;
}
/* Grow and shrink equally, start at 0 */
.item-flexible {
flex: 1;
/* Equivalent to: flex: 1 1 0; */
}
/* Grow but don't shrink, start at 200px */
.item-min-width {
flex: 1 0 200px;
}
/* Classic three-column layout */
.sidebar {
flex: 0 0 250px; /* Fixed width sidebar */
}
.main-content {
flex: 1; /* Flexible main content */
}
Override the container's align-items for individual items.
Syntax:
.item {
align-self: auto; /* Default - inherit from container */
}
Available values:
auto: Inherit from parent's align-itemsflex-start: Align to startflex-end: Align to endcenter: Center alignbaseline: Baseline alignstretch: Stretch to fillExample:
.card-container {
display: flex;
align-items: flex-start;
}
.featured-card {
align-self: center; /* This card will be centered */
}
.sticky-card {
align-self: flex-end; /* This card will align to bottom */
}
Use cases:
The order property allows you to change the visual order of flex items without modifying your HTML structure.
Syntax:
.item {
order: 0; /* Default */
}
How it works:
Examples:
.header-logo {
order: -1; /* Appears first */
}
.header-search {
order: 0; /* Default position */
}
.header-menu {
order: 1; /* Appears last */
}
Responsive reordering:
/* Mobile: Menu comes first */
.mobile-menu {
order: -1;
}
.content {
order: 0;
}
.sidebar {
order: 1;
}
/* Desktop: Restore natural order */
@media (min-width: 768px) {
.mobile-menu,
.content,
.sidebar {
order: 0;
}
}
Use cases:
Accessibility Note: The order property only changes visual order, not tab order or screen reader order. For accessibility, ensure your HTML structure makes sense.
Let's put all of these concepts together with practical, real-world examples. These examples demonstrate common patterns you'll use in everyday development.
We'll build a responsive card layout that automatically adjusts to different screen sizes while maintaining consistent spacing and proportions.
HTML:
<div class="card-container">
<div class="card">
<h3>Card Title 1</h3>
<p>Card content goes here</p>
</div>
<div class="card">
<h3>Card Title 2</h3>
<p>Card content goes here</p>
</div>
<div class="card">
<h3>Card Title 3</h3>
<p>Card content goes here</p>
</div>
<div class="card">
<h3>Card Title 4</h3>
<p>Card content goes here</p>
</div>
</div>
CSS:
.card-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: space-between;
padding: 20px;
}
.card {
flex: 1 1 300px; /* Grow, shrink, min-width 300px */
padding: 20px;
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.card h3 {
margin-top: 0;
}
What this does:
A classic three-column layout with header and footer.
HTML:
<div class="page">
<header class="header">Header</header>
<div class="main-content">
<aside class="sidebar">Sidebar</aside>
<main class="content">Main Content</main>
<aside class="ads">Ads</aside>
</div>
<footer class="footer">Footer</footer>
</div>
CSS:
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.header,
.footer {
padding: 20px;
background: #1f2937;
color: white;
}
.main-content {
display: flex;
flex: 1; /* Take remaining space */
gap: 20px;
padding: 20px;
}
.sidebar {
flex: 0 0 200px; /* Fixed width */
background: #f3f4f6;
}
.content {
flex: 1; /* Flexible main content */
background: white;
}
.ads {
flex: 0 0 160px; /* Fixed width */
background: #f3f4f6;
}
/* Responsive: Stack on mobile */
@media (max-width: 768px) {
.main-content {
flex-direction: column;
}
.sidebar,
.ads {
flex: 1 1 auto;
}
}
HTML:
<nav class="navbar">
<div class="logo">Logo</div>
<ul class="nav-menu">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Contact</a></li>
</ul>
<div class="nav-actions">
<button class="btn-login">Login</button>
<button class="btn-signup">Sign Up</button>
</div>
</nav>
CSS:
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
background: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.logo {
font-size: 1.5rem;
font-weight: bold;
color: #1f2937;
}
.nav-menu {
display: flex;
gap: 2rem;
list-style: none;
margin: 0;
padding: 0;
}
.nav-menu a {
text-decoration: none;
color: #4b5563;
font-weight: 500;
}
.nav-actions {
display: flex;
gap: 1rem;
}
HTML:
<div class="modal-overlay">
<div class="modal">
<h2>Modal Title</h2>
<p>Modal content goes here</p>
<button>Close</button>
</div>
</div>
CSS:
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
/* Perfect centering */
display: flex;
justify-content: center;
align-items: center;
}
.modal {
background: white;
padding: 2rem;
border-radius: 8px;
max-width: 500px;
width: 90%;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh; /* Full viewport height */
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.columns {
display: flex;
gap: 20px;
}
.column {
flex: 1; /* All columns grow equally */
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1; /* Takes up remaining space */
}
Great news! Flexbox has excellent browser support across all modern browsers.
| Browser | Version |
|---|---|
| Chrome | 29+ |
| Firefox | 28+ |
| Safari | 9+ |
| Edge | 12+ |
| Opera | 17+ |
| iOS Safari | 9+ |
| Android Browser | 4.4+ |
For older browsers, you might need vendor prefixes. However, modern build tools and autoprefixer typically handle this automatically.
Manual prefixing example:
.container {
display: -webkit-box; /* Old Safari, iOS, Android */
display: -ms-flexbox; /* IE 10 */
display: -webkit-flex; /* Safari */
display: flex; /* Standard */
}
Recommendation: Use a CSS preprocessor or build tool with autoprefixer to handle vendor prefixes automatically.
Follow these best practices to create efficient, maintainable, and accessible Flexbox layouts.
Always set display: flex on the parent container element first. This establishes the flex formatting context.
/* Good */
.container {
display: flex;
gap: 20px;
}
Start with flex-direction: column for mobile, then switch to row for larger screens.
Flexbox excels at one-dimensional layouts. For complex two-dimensional grids, consider CSS Grid instead.
/* Good */
.item {
flex: 1;
}
You've just learned one of the most powerful tools in modern CSS. With Flexbox in your toolkit, you're well-equipped to tackle a wide range of layout challenges. Experiment with different properties, combine them in creative ways, and soon you'll be crafting responsive, flexible layouts with ease. Happy coding!