Flexbox is the CSS layout module built for arranging items along a single row or column, and it's still the tool reached for most often when aligning a navbar, spacing out a button group, or building a card row. This guide covers every container and item property, the parts people get stuck on most (flex-direction, wrapping, and spacing), real layout recipes, a flexbox vs. grid comparison, and a compact cheat sheet at the end.
Flex Containers and Flex Items
Flexbox works in a parent/child relationship. Turn any element into a flex container with display: flex (or inline-flex to keep the container itself inline). Every direct child automatically becomes a flex item and follows flexbox's alignment rules, no extra markup required.
.container { display: flex; }
Two axes matter here: the main axis runs in the direction set by flex-direction, and the cross axis runs perpendicular to it. Properties starting with justify- work along the main axis; properties starting with align- work along the cross axis. That single rule of thumb resolves most flexbox confusion.
flex-direction: Row vs. Column
flex-direction sets the main axis and, by extension, decides whether your layout reads as a row or a column.
What is the default value of flex-direction? It's row. If you don't set flex-direction at all, items lay out left-to-right on a single horizontal line.
/* default: row */ .container { display: flex; flex-direction: row; /* optional, this is the default */ }
.container { display: flex; flex-direction: column; }
All four values:
| Value | Effect |
|---|---|
| row | Default. Items placed left-to-right in a horizontal line. |
| row-reverse | Same axis, items placed right-to-left. |
| column | Items placed top-to-bottom in a vertical line. |
| column-reverse | Same axis, items placed bottom-to-top. |
Reversing order? row-reverse and column-reverse only change the visual order. The underlying DOM order, keyboard tab order, and screen reader reading order stay exactly as written in your HTML. For layouts where reading order matters, reorder the markup itself instead of relying on a reverse value alone.
Controlling How Many Items Fit Per Row
This is one of the most common flexbox questions, and it trips people up because flexbox has no direct "items per row" or "column count" setting the way CSS Grid does. Two properties get you there instead.
flex-wrap decides whether items are forced onto one line or allowed to wrap onto multiple lines once they run out of room:
.container { display: flex; flex-wrap: wrap; /* default is nowrap */ }
Then give each item a flex-basis (or plain width) that's a fraction of the container. Roughly three items per row, accounting for gap:
.item { flex: 1 1 calc(33.333% - 1rem); }
Want an exact, guaranteed count regardless of content length? That's what CSS Grid's repeat() function is built for: grid-template-columns: repeat(3, 1fr) gives you exactly three columns every time. Our CSS Grid Generator builds that output visually if you'd rather not write it by hand. See the flexbox vs. grid comparison below for when to reach for which.
flex-flow is shorthand for flex-direction and flex-wrap together: flex-flow: row wrap;.
Spacing Between Flex Items
Use gap on the container to add consistent spacing between items without margin hacks:
.container { display: flex; gap: 1rem; /* space between every item, both axes when wrapped */ }
Split it into row-gap and column-gap if you need different spacing on each axis. gap is well supported across modern browsers and is the current standard, replacing older tricks like negative margins on the container plus matching positive margins on items.
Full Property Reference
Container properties
| Property | Values | Does |
|---|---|---|
| display | flex, inline-flex | Turns the element into a flex container. |
| flex-direction | row (default), row-reverse, column, column-reverse | Sets the main axis. |
| flex-wrap | nowrap (default), wrap, wrap-reverse | Allows items to wrap onto multiple lines. |
| flex-flow | <direction> <wrap> | Shorthand for direction + wrap. |
| justify-content | flex-start (default), flex-end, center, space-between, space-around, space-evenly | Aligns items along the main axis. |
| align-items | stretch (default), flex-start, flex-end, center, baseline | Aligns items along the cross axis. |
| align-content | stretch (default), flex-start, flex-end, center, space-between, space-around | Aligns wrapped lines when there's extra cross-axis space. |
| gap | <length>, default 0 | Space between items (row-gap / column-gap individually). |
Item properties
| Property | Values | Does |
|---|---|---|
| order | integer, default 0 | Reorders items visually, lower values first. |
| flex-grow | number, default 0 | How much an item grows to fill extra space, relative to siblings. |
| flex-shrink | number, default 1 | How much an item shrinks when space is tight. |
| flex-basis | length or auto, default auto | Starting size before growing/shrinking is applied. |
| flex | grow shrink basis | Shorthand for the three above, e.g. flex: 1 1 0%. |
| align-self | auto (default), flex-start, flex-end, center, baseline, stretch | Overrides align-items for one item. |
Nested Flexbox Patterns
Flex containers nest freely, and this is how most real components are built: a card is a flex column, and its header is a flex row inside that column.
.card { display: flex; flex-direction: column; gap: 0.75rem; } .card-header { display: flex; flex-direction: row; justify-content: space-between; align-items: center; }
The outer card stacks its sections vertically; the inner header keeps its icon and title aligned horizontally, independent of how the outer container is laid out. Each nested flex container has its own independent main and cross axis, nothing about the parent's axis carries down to the child.
Real-World Recipes
Navbar
.navbar { display: flex; justify-content: space-between; align-items: center; padding: 1rem 2rem; } .navbar nav { display: flex; gap: 1.5rem; }
Equal-Height Cards
align-items: stretch is the default, so cards in a flex row are already equal height without extra CSS, as long as you don't override it on the items.
.card-row { display: flex; gap: 1.5rem; /* align-items: stretch is the default, no extra rule needed */ } .card { flex: 1 1 250px; }
Centering Anything
.center { display: flex; justify-content: center; align-items: center; min-height: 100vh; }
Sticky Footer
body { display: flex; flex-direction: column; min-height: 100vh; } main { flex: 1; /* grows to push footer down */ }
Skip the syntax, build it visually
Prefer to drag, drop, and see the CSS update live? The Flexbox Generator gives you the same properties from this guide with a real-time preview, plus CSS, Tailwind, and Bootstrap output.
Open the Flexbox Generator →Using Flexbox with Tailwind CSS
Tailwind maps almost every flexbox property to a utility class directly:
| CSS | Tailwind |
|---|---|
| display: flex | flex |
| flex-direction: row / column | flex-row / flex-col |
| flex-wrap: wrap | flex-wrap |
| justify-content: center / space-between | justify-center / justify-between |
| align-items: center | items-center |
| align-content: center | content-center |
| gap: 1rem | gap-4 |
| flex-grow: 1 | grow |
| flex-shrink: 0 | shrink-0 |
| flex-basis: 25% | basis-1/4 |
| order: 1 | order-1 |
| align-self: center | self-center |
Flexbox vs. CSS Grid
These aren't competing tools, they solve different shaped problems.
| Flexbox | CSS Grid | |
|---|---|---|
| Dimensions | One-dimensional (row or column) | Two-dimensional (rows and columns at once) |
| Best for | Component-level alignment: navbars, toolbars, button groups, card rows | Page-level layout: overall page skeleton, dashboards, image galleries |
| Sizing | Content-driven; items grow/shrink to fit | Container-driven; explicit tracks defined up front |
| Exact column counts | Achievable but indirect (flex-basis + wrap) | Direct (repeat(), grid-template-columns) |
In practice, most layouts use both: Grid lays out the page's major regions, and flexbox aligns the content inside each region. If you're building a full 2D layout, try our CSS Grid Generator alongside this guide.
Practice Flexbox Interactively
Flexbox Froggy is a well-known browser game for practicing flexbox properties by moving frogs onto lilypads with CSS. If you'd rather build and export real, usable CSS while you learn instead of solving puzzles, our free CSS Flexbox Generator gives you a live drag-and-drop preview with instant CSS, Tailwind, and Bootstrap output, plus ready-made presets for navbars, sidebars, and holy-grail layouts.
CSS Flexbox Cheat Sheet
A condensed reference for when you already know flexbox and just need the syntax:
Container
display: flex | inline-flex; flex-direction: row | row-reverse | column | column-reverse; flex-wrap: nowrap | wrap | wrap-reverse; justify-content: flex-start | center | space-between | space-around | space-evenly; align-items: stretch | flex-start | center | baseline; align-content: stretch | flex-start | center | space-between; gap: <length>;
Items
order: <integer>; /* default 0 */ flex-grow: <number>; /* default 0 */ flex-shrink: <number>; /* default 1 */ flex-basis: auto | <length>; flex: <grow> <shrink> <basis>; align-self: auto | flex-start | center | stretch;
FAQ
Is flexbox still relevant in 2026?
Yes. CSS Grid handles two-dimensional, page-level layout, but flexbox is still the standard for one-dimensional, component-level alignment: navbars, button groups, card rows, form controls. Most real layouts use both together rather than picking one over the other.
What's the difference between "flex" and "flexbox"?
Flexbox (Flexible Box Layout) is the name of the CSS layout module. flex is a shorthand property you set on flex items (flex: 1 1 0%), and display: flex is what turns a container into a flex container. In everyday conversation people use "flex" and "flexbox" interchangeably to mean the whole layout system.
What is the default value of flex-direction?
row. Items lay out left-to-right along a horizontal main axis unless you set flex-direction to column, row-reverse, or column-reverse.
How do I control how many items appear per row in flexbox?
Flexbox has no direct "items per row" setting. Combine flex-wrap: wrap with a flex-basis or width on each item, e.g. flex-basis: 33.33% roughly produces three per row once gap is accounted for. For an exact, guaranteed column count regardless of content, CSS Grid's grid-template-columns: repeat(3, 1fr) is the more direct tool.
How do I add spacing between flex items?
Use the gap property on the flex container (gap: 1rem, or row-gap / column-gap separately). It's supported in every modern browser and avoids the old margin-and-negative-margin workarounds.
Flexbox vs. CSS Grid: which should I use?
Use flexbox for one-dimensional alignment along a single row or column, like a navbar or a toolbar. Use Grid when you're laying out a page or a component in two dimensions at once, with explicit rows and columns. Many layouts nest both: Grid for the overall page skeleton, flexbox for aligning content inside each grid area.
How do I reverse the order of flex items?
Set flex-direction to row-reverse or column-reverse. This only changes the visual order, not the underlying DOM order, so keyboard tab order and screen reader reading order stay the same as the source HTML. For accessibility-sensitive layouts, prefer reordering the HTML itself over relying on visual reversal alone.
Does flexbox work in all modern browsers?
Yes. Flexbox has had full support in Chrome, Firefox, Safari, and Edge for a decade and is considered a CSS baseline feature. Only legacy browsers like IE11 have partial or buggy support, and IE11 usage is now negligible.