CSS Flexbox: The Complete Guide for 2026
CSS Flexbox (Flexible Box Layout) is the most widely used layout system in modern CSS. It is a one-dimensional layout method designed for distributing space and aligning items within a container, either as a row or as a column. If you have ever centered an element vertically, built a navigation bar, created a card layout with a footer pinned to the bottom, or arranged form controls in a row, you have used (or wanted) Flexbox.
This guide covers everything you need to know to use Flexbox confidently in production: the fundamentals of flex containers and items, every container property (flex-direction, flex-wrap, justify-content, align-items, align-content, gap), every item property (flex-grow, flex-shrink, flex-basis, flex shorthand, order, align-self), common layout patterns you can copy directly, a detailed comparison with CSS Grid, browser support, debugging tips, and answers to the most common questions developers ask. Whether you are learning Flexbox for the first time or looking for a comprehensive reference, this is the guide to bookmark.
What Is Flexbox and When to Use It
Flexbox is a CSS layout module that provides an efficient way to distribute space among items in a container, even when their sizes are unknown or dynamic. The core idea is that a flex container can alter its items' width, height, and order to best fill the available space. Items can be stretched to fill the container or shrunk to prevent overflow.
Before Flexbox, developers relied on floats, inline-block, and table display hacks to achieve layouts that Flexbox handles natively. Vertical centering alone required multiple workarounds depending on the context. Flexbox eliminated these problems entirely when it reached full browser support around 2015.
The key characteristic of Flexbox is that it operates in one dimension at a time. You choose a main axis (horizontal or vertical), and Flexbox controls how items are distributed along that axis and aligned along the perpendicular cross axis. This is what makes it different from CSS Grid, which operates in two dimensions simultaneously.
Use Flexbox when you need to:
- Distribute items in a row or column — navigation bars, toolbars, button groups, breadcrumbs
- Center content — both horizontally and vertically, in any container
- Create equal-height columns — sidebar and content areas that stretch to match each other
- Build component-level layouts — card interiors, media objects, form rows, list items
- Reorder items visually — without changing the HTML source order
- Handle dynamic content — items that grow, shrink, or wrap based on available space
- Pin elements to edges — push a footer to the bottom of a card, or a button to the right side of a header
The mental model for Flexbox is: you define a direction (row or column), and then you control how items are spaced along that direction and aligned perpendicular to it. Content drives the sizing, and Flexbox distributes remaining space according to your rules.
The Flex Container: display: flex
Every Flexbox layout starts with a container. You activate Flexbox by setting display: flex (or display: inline-flex for an inline-level container) on the parent element. All direct children of that container immediately become flex items.
<div class="flex-container"> <!-- Flex container -->
<div class="item">A</div> <!-- Flex item -->
<div class="item">B</div> <!-- Flex item -->
<div class="item">C</div> <!-- Flex item -->
</div>
.flex-container {
display: flex;
/* By default:
- Items lay out in a row (left to right)
- Items do not wrap
- Items stretch to fill the container's height
- Items shrink to fit if the container is too narrow */
}
Only direct children become flex items. Grandchildren and deeper descendants lay out normally within their parent flex item. If you need a nested flex layout, apply display: flex to the child element as well.
Flex Container Properties
These properties are set on the flex container (the parent element) and control the overall behavior of the flex layout.
flex-direction
The flex-direction property establishes the main axis, which determines the direction flex items are placed in the container.
.container {
display: flex;
flex-direction: row; /* Default: left to right */
flex-direction: row-reverse; /* Right to left */
flex-direction: column; /* Top to bottom */
flex-direction: column-reverse; /* Bottom to top */
}
/* flex-direction: row (default)
┌──────────────────────────────────┐
│ [A] [B] [C] [D] → │ Main axis →
└──────────────────────────────────┘
flex-direction: column
┌──────────┐
│ [A] │ ↓ Main axis
│ [B] │
│ [C] │
│ [D] │
└──────────┘ */
When you change the flex-direction, the main axis and cross axis swap. This is crucial to understand: justify-content always works along the main axis, and align-items always works along the cross axis. In row mode, justify is horizontal and align is vertical. In column mode, they flip.
flex-wrap
By default, flex items try to fit on a single line. The flex-wrap property controls whether items can wrap onto multiple lines when they overflow the container.
.container {
display: flex;
flex-wrap: nowrap; /* Default: single line, items may shrink */
flex-wrap: wrap; /* Items wrap to the next line when needed */
flex-wrap: wrap-reverse; /* Items wrap upward instead of downward */
}
/* flex-wrap: nowrap (items squeeze onto one line)
┌──────────────────────────────┐
│ [A] [B] [C] [D] [E] [F] │
└──────────────────────────────┘
flex-wrap: wrap (items flow to next row)
┌──────────────────────────────┐
│ [A] [B] [C] [D] │
│ [E] [F] │
└──────────────────────────────┘ */
flex-flow (Shorthand)
The flex-flow property is a shorthand for flex-direction and flex-wrap combined:
.container {
flex-flow: row wrap; /* Direction: row, wrapping enabled */
flex-flow: column nowrap; /* Direction: column, no wrapping */
flex-flow: row-reverse wrap; /* Reversed row with wrapping */
}
justify-content
The justify-content property defines how flex items are distributed along the main axis. It controls what happens with the extra space when items do not fill the container, or how items are packed when they do.
.container {
display: flex;
justify-content: flex-start; /* Default: items packed to the start */
justify-content: flex-end; /* Items packed to the end */
justify-content: center; /* Items centered */
justify-content: space-between; /* Equal space between items, none at edges */
justify-content: space-around; /* Equal space around each item */
justify-content: space-evenly; /* Equal space between and at edges */
}
/* justify-content: flex-start (default)
│[A][B][C] │
justify-content: flex-end
│ [A][B][C]│
justify-content: center
│ [A][B][C] │
justify-content: space-between
│[A] [B] [C] │
justify-content: space-around
│ [A] [B] [C] │
justify-content: space-evenly
│ [A] [B] [C] │ */
The difference between space-around and space-evenly is subtle but matters: space-around gives each item equal margin on both sides, so the edge gaps are half the size of the gaps between items. space-evenly creates truly equal gaps everywhere, including the edges. For most designs, space-evenly looks more balanced.
align-items
The align-items property controls how flex items are aligned along the cross axis (perpendicular to the main axis). This is the property that makes vertical centering trivial.
.container {
display: flex;
align-items: stretch; /* Default: items stretch to fill the container height */
align-items: flex-start; /* Items aligned to the top */
align-items: flex-end; /* Items aligned to the bottom */
align-items: center; /* Items vertically centered */
align-items: baseline; /* Items aligned by their text baseline */
}
/* align-items: stretch (default)
┌───────────────────────┐
│[AAAAAA][BBBB][CCCCCC] │ All items stretch to same height
│[AAAAAA][BBBB][CCCCCC] │
│[AAAAAA][BBBB][CCCCCC] │
└───────────────────────┘
align-items: center
┌───────────────────────┐
│ │
│[A] [BBB] [CC] │ Items centered vertically
│ │
└───────────────────────┘
align-items: baseline
┌───────────────────────┐
│[small] │
│[small] [Medium] │ Text baselines align
│ [Medium] [BIG] │
└───────────────────────┘ */
The baseline value is particularly useful when flex items contain text of different sizes and you want the text to sit on the same line, like a navigation bar with mixed font sizes or a form row with labels and inputs.
align-content
The align-content property controls how multiple flex lines are distributed along the cross axis. This property only has an effect when flex-wrap: wrap is set and items actually wrap onto multiple lines.
.container {
display: flex;
flex-wrap: wrap;
align-content: flex-start; /* Lines packed to the start */
align-content: flex-end; /* Lines packed to the end */
align-content: center; /* Lines centered */
align-content: space-between; /* Equal space between lines */
align-content: space-around; /* Equal space around each line */
align-content: space-evenly; /* Equal space between and at edges */
align-content: stretch; /* Default: lines stretch to fill container */
}
/* align-content: flex-start align-content: center
┌────────────────────┐ ┌────────────────────┐
│ [A] [B] [C] [D] │ │ │
│ [E] [F] │ │ [A] [B] [C] [D] │
│ │ │ [E] [F] │
│ │ │ │
└────────────────────┘ └────────────────────┘ */
Think of it this way: align-items aligns individual items within a single flex line, while align-content aligns the flex lines themselves within the container. If you only have one line of items, align-content has no visible effect.
gap
The gap property (also available as row-gap and column-gap) adds spacing between flex items without affecting the outer edges. This replaced the old pattern of using margins on items and negative margins on the container.
.container {
display: flex;
flex-wrap: wrap;
gap: 1rem; /* Equal gap in both directions */
gap: 1rem 2rem; /* 1rem between rows, 2rem between columns */
row-gap: 1rem; /* Gap between rows only */
column-gap: 2rem; /* Gap between columns only */
}
/* Before gap existed, you had to use:
.container { margin: -0.5rem; }
.item { margin: 0.5rem; }
With gap:
.container { gap: 1rem; }
That is it. No workarounds needed. */
The gap property in Flexbox is supported in all modern browsers since 2021. It is now safe to use in production without fallbacks. This is one of the most important quality-of-life improvements for Flexbox layouts.
Flex Item Properties
These properties are set on individual flex items (the direct children of a flex container) and control how each item behaves within the flex layout.
flex-grow
The flex-grow property defines how much a flex item should grow relative to the other items when there is extra space in the container. The default value is 0, meaning items do not grow.
.item {
flex-grow: 0; /* Default: item does not grow */
flex-grow: 1; /* Item grows to absorb available space */
flex-grow: 2; /* Item grows twice as much as flex-grow: 1 items */
}
/* Three items, container has 300px of extra space:
All flex-grow: 0 (default)
│[A--][B--][C--] │ Items stay at content size
All flex-grow: 1
│[A----------][B----------][C----------]│ Each gets 100px extra
A flex-grow: 2, B and C flex-grow: 1
│[A-----------------][B--------][C--------]│ A gets 150px, B and C get 75px each */
The grow factor is a ratio, not an absolute size. If one item has flex-grow: 2 and two items have flex-grow: 1, the total grow factor is 4. The first item receives 2/4 (50%) of the extra space, and the other two items each receive 1/4 (25%).
flex-shrink
The flex-shrink property defines how much a flex item should shrink relative to other items when the container is too small. The default value is 1, meaning items shrink equally.
.item {
flex-shrink: 1; /* Default: item shrinks proportionally */
flex-shrink: 0; /* Item will NOT shrink, even if container overflows */
flex-shrink: 2; /* Item shrinks twice as fast as flex-shrink: 1 items */
}
/* Common use case: prevent an icon or button from shrinking
while letting the text content shrink or truncate */
.nav-bar {
display: flex;
align-items: center;
}
.nav-bar .logo {
flex-shrink: 0; /* Logo never shrinks */
}
.nav-bar .title {
flex-shrink: 1; /* Title can shrink */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
Setting flex-shrink: 0 on an item means it will maintain its size even if the container is too narrow, potentially causing overflow. This is commonly used for fixed-width elements like icons, buttons, and logos that should never be compressed.
flex-basis
The flex-basis property defines the initial size of a flex item before any growing or shrinking is applied. It serves as the starting point for the flex algorithm.
.item {
flex-basis: auto; /* Default: use the item's width/height */
flex-basis: 0; /* Start from zero; all space is distributed by flex-grow */
flex-basis: 200px; /* Start at 200px before growing/shrinking */
flex-basis: 30%; /* Start at 30% of the container */
flex-basis: content; /* Size based on the item's content */
}
/* flex-basis: auto vs flex-basis: 0 with flex-grow: 1
flex-basis: auto + flex-grow: 1
│[Short──────][A Longer Item──────────][Med────────]│
Each item starts at its content size, then extra space is split equally.
Items with more content end up wider.
flex-basis: 0 + flex-grow: 1
│[Short──────────][Longer────────────][Med──────────]│
All items start at 0, so all space is split equally.
Items are the same width regardless of content. */
The distinction between flex-basis: auto and flex-basis: 0 is one of the most important concepts in Flexbox. With auto, the content size matters; extra space is distributed after content is measured. With 0, all space is distributed equally because every item starts from zero. This is why flex: 1 (which sets flex-basis to 0%) creates equal-width items.
flex (Shorthand)
The flex shorthand sets flex-grow, flex-shrink, and flex-basis in one declaration. This is the recommended way to control flex item sizing because the shorthand sets sensible defaults for the values you omit.
/* The most common flex values */
.item { flex: 0 1 auto; } /* Default: don't grow, can shrink, auto basis */
.item { flex: 1; } /* Shorthand for: flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
.item { flex: auto; } /* Shorthand for: flex-grow: 1, flex-shrink: 1, flex-basis: auto */
.item { flex: none; } /* Shorthand for: flex-grow: 0, flex-shrink: 0, flex-basis: auto */
.item { flex: 2; } /* flex-grow: 2, flex-shrink: 1, flex-basis: 0% */
.item { flex: 1 1 200px; } /* Grow and shrink equally, starting at 200px */
/* Equal-width items: */
.item { flex: 1; } /* All items get equal space */
/* Sidebar + content: */
.sidebar { flex: 0 0 250px; } /* Fixed at 250px, won't grow or shrink */
.content { flex: 1; } /* Takes all remaining space */
/* 1:2:1 ratio: */
.left { flex: 1; }
.center { flex: 2; }
.right { flex: 1; }
Always prefer the flex shorthand over setting individual properties. The shorthand intelligently sets defaults: flex: 1 sets flex-basis to 0%, which is almost always what you want when distributing space equally. Setting only flex-grow: 1 leaves flex-basis at auto, which produces different (usually unwanted) results.
order
The order property controls the visual order of flex items without changing the HTML source order. Items are sorted by their order value in ascending order, with items of the same value maintaining their source order.
.item { order: 0; } /* Default: all items have order 0 */
/* Move an item to the end */
.item-last { order: 1; }
/* Move an item to the beginning */
.item-first { order: -1; }
/* HTML: [A] [B] [C]
A: order 2, B: order 1, C: order -1
Visual: [C] [B] [A] */
/* Practical example: mobile-first navigation */
.nav-logo { order: 0; } /* Logo first on all screens */
.nav-links { order: 2; } /* Links last on mobile */
.nav-burger { order: 1; } /* Burger menu second */
@media (min-width: 768px) {
.nav-links { order: 1; } /* Links in the middle on desktop */
.nav-burger { display: none; }
}
Use order sparingly. While it is powerful for responsive reordering, it creates a disconnect between the visual order and the DOM order, which can confuse keyboard navigation and screen readers. Always test tab order when using order.
align-self
The align-self property overrides the container's align-items value for a specific item. It accepts the same values as align-items.
.container {
display: flex;
align-items: flex-start; /* All items aligned to the top */
}
.special-item {
align-self: flex-end; /* This item aligned to the bottom */
align-self: center; /* This item vertically centered */
align-self: stretch; /* This item stretches full height */
align-self: baseline; /* This item aligns by text baseline */
}
/* align-items: flex-start on container, align-self: flex-end on C
┌──────────────────────────────┐
│ [A] [B] │
│ │
│ [C] │ C pushed to the bottom
└──────────────────────────────┘ */
Note that there is no justify-self in Flexbox. To push individual items along the main axis, use margin-left: auto or margin-right: auto (or the logical equivalents margin-inline-start and margin-inline-end). Auto margins absorb all available space in a given direction, effectively pushing adjacent items away.
/* Push an item to the right side of a flex row */
.container { display: flex; }
.push-right { margin-left: auto; }
/* [A] [B] [C]
C has margin-left: auto, pushing it to the right */
/* Common pattern: logo left, nav right */
.header {
display: flex;
align-items: center;
}
.header .logo { /* stays left by default */ }
.header .nav { margin-left: auto; }
Common Flexbox Layout Patterns
Here are the most practical Flexbox patterns you will use in real projects. Each one is production-ready and can be copied directly into your code.
Pattern 1: Navigation Bar
.navbar {
display: flex;
align-items: center;
padding: 0.75rem 1.5rem;
background: #1a1a2e;
}
.navbar .logo {
font-weight: 700;
font-size: 1.25rem;
flex-shrink: 0;
}
.navbar .nav-links {
display: flex;
gap: 1.5rem;
margin-left: auto; /* Push links to the right */
}
.navbar .nav-links a {
text-decoration: none;
color: #d1d5db;
}
/* ┌─────────────────────────────────────────┐
│ [Logo] [Home] [About] [Contact] │
└─────────────────────────────────────────┘ */
Pattern 2: Card with Footer Pinned to Bottom
.card {
display: flex;
flex-direction: column;
background: #1a1a2e;
border-radius: 8px;
overflow: hidden;
height: 100%; /* Fill the parent container */
}
.card img {
width: 100%;
height: 200px;
object-fit: cover;
}
.card .body {
padding: 1.25rem;
flex: 1; /* Grow to fill available space */
}
.card .footer {
padding: 1rem 1.25rem;
margin-top: auto; /* Push footer to the bottom */
border-top: 1px solid rgba(255,255,255,0.08);
}
/* ┌──────────────┐ ┌──────────────┐
│ [image] │ │ [image] │
│ │ │ │
│ Short text │ │ Much longer │
│ │ │ text that │
│ │ │ takes up │
│ │ │ more space │
│──────────────│ │──────────────│
│ [Footer] │ │ [Footer] │ ← aligned!
└──────────────┘ └──────────────┘ */
Pattern 3: Perfect Centering
/* Center anything horizontally and vertically */
.center-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* That is it. Two properties. The decades-long struggle
with vertical centering in CSS is completely solved. */
/* ┌────────────────────────────────┐
│ │
│ │
│ [Centered Content] │
│ │
│ │
└────────────────────────────────┘ */
Pattern 4: Holy Grail Layout
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.page header {
padding: 1rem 2rem;
background: #16213e;
}
.page .body {
display: flex;
flex: 1; /* Middle section fills remaining height */
}
.page .sidebar {
flex: 0 0 250px; /* Fixed 250px, no grow, no shrink */
padding: 1rem;
background: #1a1a2e;
}
.page .content {
flex: 1; /* Content takes remaining width */
padding: 2rem;
}
.page .aside {
flex: 0 0 200px; /* Fixed 200px right sidebar */
padding: 1rem;
background: #1a1a2e;
}
.page footer {
padding: 1rem 2rem;
background: #16213e;
}
/* Stack on mobile */
@media (max-width: 768px) {
.page .body {
flex-direction: column;
}
.page .sidebar,
.page .aside {
flex-basis: auto; /* Remove fixed width */
}
}
/* Desktop:
┌──────────────────────────────────┐
│ Header │
├──────────┬──────────────┬────────┤
│ │ │ │
│ Sidebar │ Content │ Aside │
│ (250px) │ (flex: 1) │(200px) │
│ │ │ │
├──────────┴──────────────┴────────┤
│ Footer │
└──────────────────────────────────┘ */
Pattern 5: Sidebar Layout
.sidebar-layout {
display: flex;
gap: 2rem;
}
.sidebar-layout .sidebar {
flex: 0 0 280px; /* Fixed-width sidebar */
position: sticky;
top: 1rem;
align-self: flex-start;
max-height: calc(100vh - 2rem);
overflow-y: auto;
}
.sidebar-layout .main {
flex: 1;
min-width: 0; /* Prevent content from overflowing */
}
/* Responsive: stack on narrow screens */
@media (max-width: 768px) {
.sidebar-layout {
flex-direction: column;
}
.sidebar-layout .sidebar {
flex-basis: auto;
position: static;
max-height: none;
}
}
/* ┌────────────┬──────────────────────────┐
│ │ │
│ Sidebar │ Main Content │
│ (sticky) │ │
│ │ │
│ │ │
└────────────┴──────────────────────────┘ */
Pattern 6: Responsive Card Grid (Flexbox Approach)
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card-grid .card {
flex: 1 1 300px; /* Grow, shrink, min 300px basis */
max-width: 100%;
}
/* Note: This pattern has a known limitation. If the last
row has fewer items than the others, those items will
stretch to fill the entire row width. For example:
┌──────────┬──────────┬──────────┐
│ Card 1 │ Card 2 │ Card 3 │ ← 3 per row
├──────────┴──────────┴──────────┤
│ Card 4 (stretches!) │ ← Only 1 item, fills row
For equal-width cards in every row, use CSS Grid instead:
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
The Grid version handles the last row correctly. */
Pattern 7: Media Object
/* The media object: image on the left, text on the right */
.media {
display: flex;
gap: 1rem;
align-items: flex-start;
}
.media .avatar {
flex-shrink: 0; /* Prevent avatar from shrinking */
width: 48px;
height: 48px;
border-radius: 50%;
}
.media .body {
flex: 1;
min-width: 0; /* Allow text to truncate if needed */
}
.media .body .name {
font-weight: 600;
}
.media .body .text {
color: #9ca3af;
}
/* ┌──────────────────────────────────┐
│ [Avatar] Name Here │
│ Some text content │
│ that wraps normally │
└──────────────────────────────────┘ */
Pattern 8: Input Group
.input-group {
display: flex;
}
.input-group .prefix {
flex-shrink: 0;
padding: 0.5rem 0.75rem;
background: #2a2e3a;
border: 1px solid #3a3f4b;
border-right: none;
border-radius: 6px 0 0 6px;
display: flex;
align-items: center;
color: #9ca3af;
}
.input-group input {
flex: 1;
padding: 0.5rem 0.75rem;
border: 1px solid #3a3f4b;
border-radius: 0;
background: #1e2130;
color: #e4e4e7;
}
.input-group .suffix {
flex-shrink: 0;
padding: 0.5rem 0.75rem;
background: #3b82f6;
border: 1px solid #3b82f6;
border-radius: 0 6px 6px 0;
color: white;
cursor: pointer;
}
/* ┌──────────┬──────────────────────┬──────────┐
│ https: │ example.com │ Search │
└──────────┴──────────────────────┴──────────┘ */
Flexbox vs CSS Grid: When to Use Which
Flexbox and CSS Grid are complementary layout systems. They solve different problems and work best together. Here is a practical comparison to help you choose.
| Characteristic | Flexbox | CSS Grid |
|---|---|---|
| Dimensions | One-dimensional (row OR column) | Two-dimensional (rows AND columns) |
| Layout approach | Content-driven (items dictate layout) | Structure-driven (grid defines layout) |
| Item sizing | flex-grow, flex-shrink, flex-basis | fr unit, minmax(), auto-fit |
| Item placement | Sequential flow with optional order | Explicit line/area placement |
| Wrapping behavior | flex-wrap (items may stretch on last row) | auto-fill/auto-fit (consistent column width) |
| Overlap | Not supported natively | Items can share cells, controlled with z-index |
| Named areas | No | Yes (grid-template-areas) |
| Best for | Components, navbars, centering, card internals | Page layouts, dashboards, card grids, forms |
The simplest rule: if your layout is primarily in one direction (a row of nav links, a column of card content), use Flexbox. If you need to control both rows and columns at the same time (a page layout with header, sidebar, content, footer), use Grid. In practice, most real-world interfaces use both: Grid for the page skeleton, Flexbox for the components inside grid cells.
/* The best practice: combine both */
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.page .header {
grid-column: 1 / -1;
display: flex; /* Flexbox inside a grid cell */
align-items: center;
justify-content: space-between;
padding: 1rem 2rem;
}
.page .sidebar {
display: flex;
flex-direction: column; /* Flexbox for sidebar navigation */
gap: 0.25rem;
padding: 1rem;
}
.page .content {
padding: 2rem;
}
.page .footer {
grid-column: 1 / -1;
display: flex; /* Flexbox for footer links */
justify-content: space-between;
padding: 1rem 2rem;
}
Browser Support and Compatibility
CSS Flexbox has been universally supported since 2015 and has over 99% global browser support as of 2026. You can use it in any project without fallbacks or prefixes.
- Chrome — since version 29 (August 2013)
- Firefox — since version 28 (March 2014)
- Safari — since version 9 (September 2015)
- Edge — since version 12 (July 2015)
- Opera — since version 17 (August 2013)
The gap property for Flexbox was the last major feature to gain full support:
- Chrome — gap in Flexbox since version 84 (July 2020)
- Firefox — since version 63 (October 2018)
- Safari — since version 14.1 (April 2021)
- Edge — since version 84 (July 2020)
As of 2026, there are no Flexbox features that require vendor prefixes, @supports checks, or fallback layouts. The specification is stable and fully implemented across all current browsers. You can use every property covered in this guide with complete confidence.
Debugging Flexbox: Tips and Tools
When a Flexbox layout does not behave as expected, here are the most effective debugging strategies.
1. Use Browser DevTools Flex Inspector
Chrome, Firefox, and Edge all have dedicated Flexbox inspectors. In Chrome DevTools, select a flex container in the Elements panel and click the "flex" badge to overlay alignment guides, main/cross axis indicators, and space distribution visualization. Firefox's Flexbox inspector is particularly good, showing grow/shrink calculations and free space distribution.
2. Check min-width: 0
The most common Flexbox bug is content overflowing its container. By default, flex items have min-width: auto, which means they cannot shrink smaller than their content. If you have a long word, a URL, or a pre block inside a flex item, it will overflow.
/* The fix: allow the item to shrink below its content size */
.flex-item {
min-width: 0; /* For row direction */
/* or */
min-height: 0; /* For column direction */
overflow: hidden; /* Optional: clip overflow */
}
3. Understand flex-basis vs width
When both flex-basis and width are set, flex-basis wins (for flex-direction: row). This causes confusion when developers set width: 200px on a flex item and it does not work as expected because flex-basis defaults to auto, which resolves to the item's width. If you are using the flex shorthand, it may override your width.
/* This item will NOT be 200px wide if flex: 1 is set */
.item {
width: 200px;
flex: 1; /* flex-basis is now 0%, overriding width */
}
/* To get a fixed 200px item in a flex container: */
.item {
flex: 0 0 200px; /* No grow, no shrink, basis 200px */
}
4. Watch for Margin Collapse
Margins do not collapse in Flexbox (unlike normal block flow). This is actually a benefit, but if you are migrating from a non-flex layout, the spacing will change. Use gap instead of margins for consistent spacing between flex items.
5. Check for Conflicting Flex Properties
/* Common mistake: setting width on a flex item */
.sidebar {
width: 250px; /* This works only if flex-shrink is 0 */
/* Without this, the sidebar WILL shrink below 250px */
flex-shrink: 0; /* Add this to make width fixed */
}
/* Better approach: use flex shorthand */
.sidebar {
flex: 0 0 250px; /* No grow, no shrink, 250px basis */
}
6. The Stretched Image Problem
Images inside flex containers often stretch unexpectedly because align-items defaults to stretch. Fix this by setting align-self: flex-start on the image, or align-items: flex-start on the container.
.flex-container img {
align-self: flex-start; /* Prevent image from stretching */
max-width: 100%;
height: auto;
}
Complete Flexbox Property Reference
Here is a concise reference of every Flexbox property, grouped by container and item.
Container Properties
/* Activate Flexbox */
display: flex; /* or inline-flex */
/* Direction and wrapping */
flex-direction: row | row-reverse | column | column-reverse;
flex-wrap: nowrap | wrap | wrap-reverse;
flex-flow: <direction> <wrap>; /* Shorthand */
/* Main-axis distribution */
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
/* Cross-axis alignment */
align-items: stretch | flex-start | flex-end | center | baseline;
/* Multi-line cross-axis distribution */
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch;
/* Gaps */
gap: <row-gap> <column-gap>;
row-gap: <length>;
column-gap: <length>;
Item Properties
/* Sizing */
flex-grow: <number>; /* Default: 0 */
flex-shrink: <number>; /* Default: 1 */
flex-basis: <length> | auto; /* Default: auto */
flex: <grow> <shrink> <basis>; /* Recommended shorthand */
/* Ordering */
order: <integer>; /* Default: 0 */
/* Individual alignment (overrides container's align-items) */
align-self: auto | flex-start | flex-end | center | baseline | stretch;
Frequently Asked Questions
What is the difference between justify-content and align-items in Flexbox?
justify-content controls the distribution of items along the main axis (horizontal by default in flex-direction: row), while align-items controls alignment along the cross axis (vertical by default). If you change flex-direction to column, the axes swap: justify-content then controls vertical distribution and align-items controls horizontal alignment. Think of justify-content as "spacing along the flow direction" and align-items as "alignment perpendicular to the flow direction."
When should I use Flexbox instead of CSS Grid?
Use Flexbox for one-dimensional layouts where items flow in a single direction (a row or a column) and the content size should drive the layout. Common Flexbox use cases include navigation bars, button groups, card internal layout, centering content, and toolbars. Use CSS Grid for two-dimensional layouts where you need explicit control over both rows and columns simultaneously, such as page-level layouts, dashboard widgets, and responsive card grids. In practice, most production layouts use both: Grid for the outer page structure and Flexbox for components inside grid cells.
What does flex: 1 mean and how is it different from flex-grow: 1?
flex: 1 is shorthand for flex-grow: 1, flex-shrink: 1, flex-basis: 0%. This means the item can grow to fill available space, can shrink if needed, and starts with a base size of zero before distributing space. In contrast, flex-grow: 1 by itself only sets the grow factor while leaving flex-shrink and flex-basis at their defaults (1 and auto, respectively). The key difference is flex-basis: with flex: 1 it is 0% (all space is distributed equally), but with just flex-grow: 1 it remains auto (each item's content size is respected before extra space is distributed). Use flex: 1 when you want truly equal-width items.
Summary
CSS Flexbox is the go-to layout system for one-dimensional component layouts in 2026. It handles navigation bars, card interiors, centering, toolbars, form rows, media objects, and any situation where you need to distribute items along a single axis with flexible spacing and alignment. Here is a quick decision framework:
- Start with
display: flexon the container. - Set
flex-directiontorow(default) orcolumndepending on your flow direction. - Use
justify-contentto control spacing along the main axis (center,space-between, andspace-evenlyare the most common values). - Use
align-itemsto control alignment along the cross axis (centerandstretchare the most common values). - Use
gapfor spacing between items. Never use margins for gaps in Flexbox. - Use
flex: 1on items that should grow to fill available space, andflex: 0 0 <size>on items that should stay fixed. - Use
margin-left: auto(ormargin-inline-start: auto) to push items to the opposite side of the container. - Combine with CSS Grid: Grid for the outer page layout, Flexbox for the component-level layout inside grid cells.
The best way to internalize Flexbox is to build real layouts. Start with a navigation bar and a centered hero section, then work up to card layouts and holy grail pages. Within a few components, the main-axis and cross-axis mental model will become second nature.
For a quick-reference table of every Flexbox property, keep our CSS Flexbox Cheat Sheet bookmarked. To experiment with Flexbox properties visually, use the Flexbox Playground. And if you need two-dimensional layouts, read our CSS Grid Complete Guide.