The Quick Answer
CSS Flexbox is a one-dimensional layout model that distributes space among items in a container and aligns them along a main axis and a cross axis.
Set display: flex on a container, and its direct children become flex items that you can align, space, stretch, and reorder using a small set of properties.
.container {
display: flex;
justify-content: center; /* main axis alignment */
align-items: center; /* cross axis alignment */
gap: 1rem; /* space between items */
}
Try different property combinations in our Flexbox Playground to see results in real time.
How Flexbox Works: Two Axes
Every flex container has two axes:
- Main axis -- the direction flex items are placed in. Default is horizontal (left to right).
- Cross axis -- perpendicular to the main axis. Default is vertical (top to bottom).
flex-direction: row (default)
Main axis: ------>
Cross axis: |
v
flex-direction: column
Main axis: |
v
Cross axis: ------>
Understanding which axis is which determines how justify-content and align-items behave. justify-content always works on the main axis. align-items always works on the cross axis.
Container Properties
These properties go on the parent element with display: flex.
flex-direction
Controls the main axis direction.
| Value | Main Axis | Items Flow |
|---|---|---|
row (default) |
Horizontal | Left to right |
row-reverse |
Horizontal | Right to left |
column |
Vertical | Top to bottom |
column-reverse |
Vertical | Bottom to top |
flex-wrap
Controls whether items wrap to new lines.
| Value | Behavior |
|---|---|
nowrap (default) |
All items stay on one line; they shrink to fit |
wrap |
Items wrap to the next line when they overflow |
wrap-reverse |
Items wrap upward instead of downward |
justify-content
Aligns items along the main axis.
| Value | Effect |
|---|---|
flex-start (default) |
Pack items to the start |
flex-end |
Pack items to the end |
center |
Center items |
space-between |
Equal space between items; no space at edges |
space-around |
Equal space around each item (half-space at edges) |
space-evenly |
Equal space between items and at edges |
align-items
Aligns items along the cross axis.
| Value | Effect |
|---|---|
stretch (default) |
Items stretch to fill the container's cross size |
flex-start |
Align to the start of the cross axis |
flex-end |
Align to the end of the cross axis |
center |
Center on the cross axis |
baseline |
Align items by their text baselines |
align-content
Controls spacing of wrapped lines along the cross axis. Only applies when flex-wrap: wrap is set and there are multiple lines. Accepts the same values as justify-content plus stretch.
gap
Sets the spacing between flex items. Accepts one value (both axes) or two values (row-gap and column-gap).
.container {
display: flex;
gap: 1rem; /* 1rem between all items */
gap: 1rem 2rem; /* 1rem row gap, 2rem column gap */
}
gap is supported in all modern browsers for Flexbox since 2021. It replaces the older workaround of using margins on items. See MDN: gap.
Item Properties
These properties go on the flex items (direct children of the flex container).
flex-grow
Controls how much an item grows relative to siblings when extra space is available. Default is 0 (do not grow).
.item-a { flex-grow: 1; } /* gets 1 share of extra space */
.item-b { flex-grow: 2; } /* gets 2 shares of extra space */
If the container has 300px of extra space, item-a gets 100px and item-b gets 200px.
flex-shrink
Controls how much an item shrinks relative to siblings when space is insufficient. Default is 1 (shrink equally).
Setting flex-shrink: 0 prevents an item from shrinking below its basis.
flex-basis
Sets the initial size of an item before growing or shrinking. Default is auto (uses the item's width or content size).
.item { flex-basis: 200px; } /* starts at 200px, then grows/shrinks */
In a row layout, flex-basis acts like width. In a column layout, it acts like height. When both flex-basis and width are set, flex-basis takes priority.
The flex Shorthand
The flex shorthand sets flex-grow, flex-shrink, and flex-basis in one declaration.
| Shorthand | Expands To | Meaning |
|---|---|---|
flex: 0 1 auto |
grow:0, shrink:1, basis:auto | Default behavior |
flex: 1 |
grow:1, shrink:1, basis:0% | Grow to fill space equally |
flex: auto |
grow:1, shrink:1, basis:auto | Grow from content size |
flex: none |
grow:0, shrink:0, basis:auto | Fixed size, no flex |
flex: 0 0 200px |
grow:0, shrink:0, basis:200px | Fixed at 200px |
Note that flex: 1 sets the basis to 0%, not auto. This is important: it means the item ignores its content size when distributing space, so all flex: 1 items get equal widths regardless of content. This catches many people off guard. See W3C Flex Shorthand specification.
align-self
Overrides align-items for a single item. Accepts the same values.
.container { align-items: flex-start; }
.special-item { align-self: center; } /* only this item is centered */
order
Changes the visual order of an item. Default is 0. Lower values appear first.
.item-first { order: -1; } /* appears before order: 0 items */
.item-last { order: 1; } /* appears after order: 0 items */
Note: order only changes visual order, not tab order or screen reader order. Use with care for accessibility.
Six Common Layout Patterns
Pattern 1: Centering an Element (Both Axes)
.center-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
<div class="center-container">
<div class="centered-content">Centered</div>
</div>
The container needs a defined height for vertical centering to work. min-height: 100vh makes it fill the viewport.
Pattern 2: Navigation Bar (Logo Left, Links Right)
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
<nav class="navbar">
<div class="logo">Site Name</div>
<ul class="nav-links">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
space-between pushes the logo and links to opposite ends. align-items: center vertically centers them.
Pattern 3: Equal-Width Columns
.columns {
display: flex;
gap: 1rem;
}
.columns > * {
flex: 1;
}
<div class="columns">
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</div>
flex: 1 on each child gives them equal shares of the container width, regardless of content length.
Pattern 4: Sticky Footer Layout
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
main {
flex: 1;
}
<body>
<header>Header</header>
<main>Content</main>
<footer>Footer</footer>
</body>
The main element grows to fill all available vertical space, pushing the footer to the bottom even when content is short.
Pattern 5: Card Grid with Wrapping
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card {
flex: 0 1 calc(33.33% - 0.67rem);
}
<div class="card-grid">
<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 class="card">Card 5</div>
</div>
Each card takes roughly one-third of the container width (minus gap space). When the viewport narrows, cards wrap to the next row. The calc value accounts for the gap: with 3 items per row and 2 gaps, each item subtracts 2/3 of the gap size.
Pattern 6: Sidebar + Main Content
.layout {
display: flex;
gap: 2rem;
}
.sidebar {
flex: 0 0 250px; /* fixed width, no grow, no shrink */
}
.main-content {
flex: 1; /* fills remaining space */
}
<div class="layout">
<aside class="sidebar">Sidebar</aside>
<div class="main-content">Main</div>
</div>
The sidebar stays at 250px. The main content area fills the rest. Add min-width: 0 to .main-content if long words or wide elements cause overflow issues.
Common Mistakes
Not accounting for min-width
By default, flex items will not shrink below their minimum content size (the length of the longest word or widest child element). If an item refuses to shrink, add:
.item { min-width: 0; }
This allows the item to shrink below its content size. For column layouts, use min-height: 0 instead.
Confusing flex-basis with width
When both are set, flex-basis wins in a flex context. Setting width: 200px on a flex item and then flex-basis: 300px results in a starting size of 300px. Use one or the other, not both, to avoid confusion.
Forgetting that flex: 1 sets basis to 0%
flex: 1 means flex: 1 1 0%. The item's content size is ignored for space distribution. If you want items to grow from their content size, use flex: auto (which is flex: 1 1 auto) instead.
Using Flexbox when Grid is more appropriate
If you need items to align in both rows and columns simultaneously (like a data table or a two-dimensional grid), CSS Grid gives you direct control over both axes. Flexbox is one-dimensional -- it excels at distributing items along a single axis.
Flexbox Playground
Adjust every flex container and item property and see the results in real time. Includes presets for common layout patterns.
Open Flexbox PlaygroundFrequently Asked Questions
When should I use Flexbox vs CSS Grid?
Use Flexbox for one-dimensional layouts (a single row or column of items). Use Grid for two-dimensional layouts (rows and columns simultaneously). Flexbox is ideal for navigation bars, card rows, and centering. Grid is better for full page layouts and arrangements where you need control over both axes at once. The two work well together -- a Grid layout can contain Flexbox components.
How do I center a div with Flexbox?
Set the parent container to display: flex; justify-content: center; align-items: center. This centers the child both horizontally and vertically. The parent needs a defined height (e.g., min-height: 100vh) for vertical centering to be visible.
What does flex: 1 mean?
flex: 1 is shorthand for flex-grow: 1, flex-shrink: 1, flex-basis: 0%. It tells the item to grow and fill available space equally with other flex: 1 items. The 0% basis means sizing starts from zero, so all items get equal shares regardless of their content size.
How do I make flex items equal width?
Set flex: 1 on each item. This makes every item start from a 0% basis and grow equally. Alternatively, set flex-basis to a percentage like 33.33% for three columns, combined with flex-grow: 0 to prevent unequal growth.
What is the difference between justify-content and align-items?
justify-content controls alignment along the main axis (horizontal in a row layout, vertical in a column layout). align-items controls alignment along the cross axis (perpendicular to the main axis). In the default flex-direction: row, justify-content is horizontal and align-items is vertical.
How do I wrap flex items to the next line?
Add flex-wrap: wrap to the flex container. By default, Flexbox keeps all items on a single line and shrinks them to fit. With flex-wrap: wrap, items that exceed the container width flow onto the next line.
What is the difference between flex-basis and width?
flex-basis sets the initial size of a flex item before flex-grow and flex-shrink are applied. width sets the size regardless of flex context. When an element is a flex item, flex-basis takes priority over width (in row layouts) or height (in column layouts). See MDN: flex-basis.
Why is my flex item not shrinking?
The most common cause is the item's content enforcing a minimum size. By default, flex items will not shrink below their min-content size. Add min-width: 0 (for row layouts) or min-height: 0 (for column layouts) to the item, or use overflow: hidden to allow the item to shrink past its content size.
How does the order property work in Flexbox?
The order property controls the visual order of flex items without changing the HTML source order. All items default to order: 0. Items with lower values appear first. Items with the same value follow their source order. Note that order only changes visual rendering, not tab order or screen reader order.
Can I use Flexbox for a grid of cards?
Yes. Set the container to display: flex with flex-wrap: wrap, and give each card a flex-basis (e.g., calc(33.33% - 1rem) for three columns with gaps). Use the gap property for consistent spacing. For complex grid layouts with strict row-and-column alignment, CSS Grid may be a better fit.