What Is CSS Flexbox?
The Flexible Box Layout, commonly called Flexbox, is a CSS layout module designed to arrange elements efficiently along a single axis—either horizontally or vertically. It provides a predictable way to distribute space, align content, and handle dynamic sizing, even when the size of the items is unknown or changes. Flexbox works by turning a parent element into a flex container and its direct children into flex items. Once you declare display: flex; on a container, you gain access to a rich set of alignment, ordering, and sizing properties that replace many fragile float-based or table-based hacks.
Why Flexbox Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Before Flexbox, developers relied on floats, inline-block, and absolute positioning to build layouts. Those techniques often required complex calculations, extra markup, and clearfix hacks. Flexbox solves these pain points:
- True vertical centering – effortlessly align items both horizontally and vertically.
- Equal-height columns – items inside a flex container automatically stretch to match the tallest sibling.
- Dynamic spacing – distribute remaining space with
justify-contentor let items grow to fill gaps. - Source-order independence – visually reorder items without changing HTML structure using
order. - Responsive-friendly – combine with
flex-wrapand media queries for fluid layouts.
Flexbox is now supported in all modern browsers and is the go-to tool for one-dimensional layouts—navigation bars, card rows, centring a single element, and component-level arrangements.
How Flexbox Works: Core Concepts
Flex Container vs. Flex Items
The moment you apply display: flex; (or display: inline-flex;) to a parent, that parent becomes the flex container. Its direct children automatically become flex items. Only those direct children are affected; nested elements remain block or inline unless they themselves become flex containers.
<div class="container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
.container {
display: flex;
}
Main Axis and Cross Axis
Understanding the two axes is the key to mastering Flexbox. The main axis is the direction in which flex items are laid out (defined by flex-direction). The cross axis is perpendicular to it. Properties like justify-content work along the main axis, while align-items and align-self work along the cross axis.
- Default:
flex-direction: row;→ main axis is horizontal (left to right), cross axis is vertical (top to bottom). - When
flex-direction: column;→ main axis is vertical (top to bottom), cross axis is horizontal.
Flex Direction
flex-direction sets the direction of the main axis. Available values:
row(default) – items flow left to right (in LTR writing mode).row-reverse– items flow right to left.column– items flow top to bottom.column-reverse– items flow bottom to top.
.container {
display: flex;
flex-direction: row; /* or column, row-reverse, column-reverse */
}
Wrapping with flex-wrap
By default, flex items try to fit on one line. Use flex-wrap to allow items to wrap onto multiple lines when they exceed the container's width.
nowrap(default) – all items on one line; may overflow.wrap– items wrap onto additional lines from top to bottom.wrap-reverse– items wrap from bottom to top.
.container {
display: flex;
flex-wrap: wrap; /* items will wrap if necessary */
}
You can combine both with the shorthand flex-flow: row wrap;.
Justify Content – Main Axis Alignment
justify-content controls how flex items are distributed along the main axis. It’s one of the most frequently used properties.
flex-start– items pack toward the start of the main axis.flex-end– items pack toward the end.center– items are centered along the main axis.space-between– first item at start, last at end, equal space between each pair.space-around– equal space around each item (half-space at edges).space-evenly– equal space between items and container edges.
.container {
display: flex;
justify-content: space-between;
}
Align Items and Align Content – Cross Axis Alignment
align-items positions flex items along the cross axis of the current line. This is what makes vertical centering trivial.
stretch(default) – items stretch to fill the cross axis (creates equal height columns).flex-start– items align at the start of the cross axis.flex-end– items align at the end.center– items are centered along the cross axis.baseline– items align by their text baseline.
.container {
display: flex;
align-items: center; /* vertically centers items when flex-direction: row */
}
When you have multiple wrapped lines, align-content controls how those lines are distributed on the cross axis (similar to justify-content but for lines). It works only when flex-wrap is set and there are multiple lines.
stretch,flex-start,flex-end,center,space-between,space-around,space-evenly.
.container {
display: flex;
flex-wrap: wrap;
align-content: space-between;
}
Flex Item Properties: flex-grow, flex-shrink, flex-basis
These properties are set on the flex items themselves and control how they grow, shrink, and what their initial size should be.
flex-grow(default 0) – dictates how much the item should expand relative to others when there is free space.flex-shrink(default 1) – dictates how much the item should shrink relative to others when there isn’t enough space.flex-basis(default auto) – sets the initial main size before free space is distributed; can be a length (e.g., 200px) orauto(based on content).
.item {
flex-grow: 1; /* can grow to fill space */
flex-shrink: 0; /* will not shrink if container is too small */
flex-basis: 200px; /* starts at 200px wide */
}
The flex Shorthand
Instead of setting three separate values, use the flex shorthand: flex: <grow> <shrink> <basis>. Common patterns:
flex: 1;– equivalent toflex: 1 1 0;(item can grow and shrink, starts from zero basis).flex: auto;–flex: 1 1 auto;(grows/shrinks based on content size).flex: none;–flex: 0 0 auto;(item doesn't grow or shrink, retains content-based size).flex: 0 0 250px;– fixed-size item, no flexibility.
.sidebar {
flex: 0 0 300px; /* fixed width sidebar */
}
.main-content {
flex: 1; /* takes remaining space */
}
Align Self – Individual Cross Axis Override
align-self on a flex item overrides the container’s align-items for that specific item. Accepts the same values: stretch, flex-start, flex-end, center, baseline.
.item:nth-child(2) {
align-self: flex-end; /* moves only this item to the cross-axis end */
}
Order – Visual Source Reordering
The order property assigns an integer to flex items, determining their visual order along the main axis. All items default to order: 0;. Items are sorted by order value (lowest first), then by source order. Use cautiously as it can disconnect visual order from DOM order, affecting accessibility.
.item:first-child {
order: 2; /* appears after item with order 1 */
}
.item:last-child {
order: -1; /* appears before all items with default order 0 */
}
Practical Examples
Centering a Single Element
The classic "centering" problem is solved with three lines:
.parent {
display: flex;
justify-content: center; /* main axis center */
align-items: center; /* cross axis center */
height: 100vh; /* give container a height */
}
Creating a Navigation Bar
A common navbar pattern: logo on the left, navigation links on the right.
<nav class="navbar">
<div class="logo">Brand</div>
<ul class="nav-links">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.nav-links {
display: flex;
list-style: none;
gap: 1.5rem;
}
Building a Responsive Card Layout
Using flex-wrap and flex-basis to create a grid-like row of cards that wrap on smaller screens.
<div class="card-container">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
<div class="card">Card 4</div>
</div>
.card-container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: center;
}
.card {
flex: 1 1 300px; /* grow, shrink, basis */
max-width: 350px;
background: #f4f4f4;
padding: 1rem;
border-radius: 8px;
}
Each card starts at 300px, can grow to fill remaining space, and shrinks if the viewport narrows. When they can no longer fit side by side, they wrap.
Holy Grail Layout with Flexbox
A classic header-footer with sticky footer, main content area, and sidebars.
<div class="wrapper">
<header>Header</header>
<div class="main-area">
<aside class="sidebar-left">Left Sidebar</aside>
<main>Main Content</main>
<aside class="sidebar-right">Right Sidebar</aside>
</div>
<footer>Footer</footer>
</div>
body, html { margin: 0; height: 100%; }
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
}
header, footer {
flex: 0 0 auto; /* fixed height based on content */
background: #333; color: white; padding: 1rem;
}
.main-area {
display: flex;
flex: 1; /* takes remaining vertical space */
}
.sidebar-left, .sidebar-right {
flex: 0 0 200px; /* fixed width */
background: #eee; padding: 1rem;
}
main {
flex: 1; /* takes remaining horizontal space */
padding: 1rem;
}
The outer wrapper uses a column flex container to push the footer to the bottom. The inner row (.main-area) is a flex container with fixed sidebars and a flexible main section.
Best Practices
1. Use Flexbox for One-Dimensional Layouts, CSS Grid for Two Dimensions
Flexbox excels at distributing items along a single axis, perfect for components like navigation, button groups, or centering. When you need control over both rows and columns simultaneously—like a full page layout—consider CSS Grid. Combining both is powerful: use Grid for the overall page structure and Flexbox for internal component alignment.
2. Prefer the flex Shorthand
Always use the shorthand flex: <grow> <shrink> <basis> rather than setting individual longhand properties. It ensures predictable behavior because it sets the basis correctly and avoids common pitfalls where missing values default to 0 or auto unexpectedly. For example, flex: 1; is safer than flex-grow: 1; alone.
3. Mind the Source Order vs. Visual Order
The order property is tempting for quick reordering, but it only changes the visual rendering. Screen readers and keyboard navigation still follow the DOM order. Avoid using order for critical content reordering; instead, adjust your HTML structure or use CSS Grid’s placement features when accessible reordering is required.
4. Use gap for Spacing Between Items
Instead of margin hacks, use the gap property (row-gap, column-gap, or the shorthand gap) on the flex container. It creates consistent spacing between flex items without affecting the first or last item’s distance from the container edges. This is especially useful for wrapped layouts.
.container {
display: flex;
flex-wrap: wrap;
gap: 1rem; /* 1rem gap between items, both horizontally and vertically */
}
5. Combine flex-basis with min-width for Better Control
When you want items to have a minimum size but also grow, set both flex-basis and min-width. For example, a card that should be at least 250px but can expand:
.card {
flex: 1 1 250px;
min-width: 250px;
}
This prevents items from shrinking below the desired size when the container gets very narrow.
6. Test with Variable Content Lengths
Flexbox shines with dynamic content, but it can break assumptions if you only test with uniform items. Always test with different content lengths (long text, short text) to ensure alignment, wrapping, and sizing behave as expected. Use align-items: flex-start if you don’t want stretched heights for all items in a row.
7. Use Browser DevTools Flex Inspectors
Modern browsers offer visual flex inspectors. In Chrome or Firefox DevTools, clicking on a flex container reveals an overlay showing the main/cross axes, gap areas, and item outlines. Use these tools to debug alignment issues quickly instead of guessing.
8. Avoid Deep Nesting of Flex Containers Unnecessarily
While Flexbox is robust, too many nested flex containers can lead to performance and maintainability issues. If a child only needs simple alignment, consider whether its parent already provides the necessary axis control. Flatten your layout where possible.
9. Provide Fallbacks for Legacy Browsers (If Needed)
If you must support IE10 or older, use vendor prefixes (-ms-flex) or provide a float-based fallback. For modern projects, Flexbox is universally supported. However, always check your project’s browser matrix.
10. Keep Learning: Flexbox + Grid Synergy
Flexbox isn't a silver bullet. For complex layouts, combine it with CSS Grid. For example, use Grid to define the page’s major areas (header, sidebar, main, footer) and then use Flexbox inside those areas for component-level alignment. Understanding both gives you full layout superpowers.
Conclusion
CSS Flexbox has revolutionized front-end layout by providing a predictable, intuitive model for one-dimensional arrangements. By mastering the core concepts—container vs. items, main and cross axes, and the key properties like justify-content, align-items, and the flex shorthand—you can build robust, responsive interfaces with far less code and fewer hacks. Adopt best practices like using gap for spacing, preferring the flex shorthand, and respecting source order for accessibility. Combine Flexbox with CSS Grid to handle every layout challenge, and always leverage browser DevTools to refine your designs. With these tips, you’re well-equipped to write maintainable, future-proof layouts that work across all modern browsers.