Flexbox is a one-dimensional layout system — it arranges items in a single row or column. It excels at distributing space, aligning items, and handling dynamic content sizes.
Enabling Flexbox
Apply display: flex to a container, and its direct children become flex items:
.row {
display: flex;
}<div class="row">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>By default, flex items sit in a row, don't wrap, and stretch to the container's height.
Direction and Wrapping
Control the flow direction and whether items wrap to new lines:
/* Horizontal row (default) */
.row {
display: flex;
flex-direction: row;
}
/* Vertical column */
.column {
display: flex;
flex-direction: column;
}
/* Allow items to wrap when they run out of space */
.wrap {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}When flex-wrap: wrap is set, items that don't fit on one line move to the next. Without it, items shrink to fit.
Alignment
Flexbox has two axes: the main axis (direction of flow) and the cross axis (perpendicular). Alignment properties work along these axes.
.center-both {
display: flex;
justify-content: center; /* main axis */
align-items: center; /* cross axis */
min-height: 100dvh;
}justify-content (main axis)
.container {
display: flex;
/* flex-start | center | flex-end | space-between | space-around | space-evenly */
justify-content: space-between;
}space-between— equal gaps between items, no gap at edges.space-evenly— equal gaps everywhere, including edges.
align-items (cross axis)
.container {
display: flex;
/* stretch | flex-start | center | flex-end | baseline */
align-items: center;
}stretch(default) — items fill the container's cross-axis size.baseline— items align by their text baselines (useful for mixed font sizes).
Individual item alignment
Override alignment for a single item with align-self:
.container {
display: flex;
align-items: flex-start;
}
.container .special {
align-self: flex-end;
}Gap
The gap property adds space between flex items without affecting the edges:
.row {
display: flex;
gap: 1rem; /* equal gap in both directions */
}
.grid-like {
display: flex;
flex-wrap: wrap;
row-gap: 1.5rem;
column-gap: 1rem;
}This replaces the old technique of adding margins to items and removing the margin from the last one.
Flex Items: grow, shrink, basis
These three properties control how items share available space:
.item {
flex-grow: 0; /* don't grow beyond basis (default) */
flex-shrink: 1; /* shrink if needed (default) */
flex-basis: auto; /* start at content width (default) */
}
/* Shorthand: flex: grow shrink basis */
.item {
flex: 0 1 auto; /* default behavior */
}Common patterns:
/* Item takes all available space */
.fill {
flex: 1; /* same as flex: 1 1 0% */
}
/* Item doesn't grow or shrink — fixed size */
.fixed {
flex: none; /* same as flex: 0 0 auto */
}
/* Two items split space equally */
.half {
flex: 1 1 0%;
}Common Flexbox Patterns
Navigation bar
<nav class="navbar">
<a href="/" class="logo">MySite</a>
<div class="nav-links">
<a href="/about">About</a>
<a href="/blog">Blog</a>
<a href="/contact">Contact</a>
</div>
</nav>.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.nav-links {
display: flex;
gap: 1.5rem;
}Card with footer pushed to bottom
<div class="card">
<h3>Card Title</h3>
<p>Some content that varies in length.</p>
<a href="#" class="card-link">Read more</a>
</div>.card {
display: flex;
flex-direction: column;
padding: 1.5rem;
min-height: 250px;
}
.card-link {
margin-top: auto; /* pushes to the bottom */
}Centering anything
.center {
display: flex;
justify-content: center;
align-items: center;
min-height: 100dvh;
}Input with button
<div class="search">
<input type="text" placeholder="Search...">
<button>Go</button>
</div>.search {
display: flex;
gap: 0.5rem;
}
.search input {
flex: 1; /* input takes remaining space */
}
.search button {
flex: none; /* button stays its natural size */
}Order
Change visual order without changing HTML order. Use sparingly — it can confuse keyboard navigation:
.first-visually {
order: -1; /* moves before items with default order: 0 */
}