CSS Flex Responsive
In this page:
selector {
display: flex;
flex-wrap: wrap;
}
@media (max-width: length) {
selector {
flex-direction: column;
}
}
The Wrap-Based Responsive Pattern
The simplest responsive Flexbox technique combines flex-wrap: wrap with a flex-basis (or min-width) on each item — as the container narrows, items that no longer fit on the current line automatically drop to the next one, with zero media queries involved.
This alone handles a large share of "cards reflow on mobile" layouts.
- Accepted values:
- flex-wrap: wrap — allows items to drop to the next line
- flex: 1 1 200px — grows, shrinks, ideal 200px
- min-width: <length> — sets a floor
- gap: <length> — spacing between wrapped items
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: The Wrap-Based Responsive Pattern
<style>
.row {
display: flex;
flex-wrap: wrap;
}
.card {
flex-basis: 200px;
background: steelblue;
color: white;
padding: 10px;
margin: 4px;
}
</style>
<div class="row">
<div class="card">Card</div>
<div class="card" style="background: seagreen;">Card</div>
<div class="card" style="background: coral;">Card</div>
</div>
Percentage-Based flex-basis for Column Counts
Setting flex-basis: 33.33% (roughly) on items inside a wrapping flex row gives you a rough 3-column grid that naturally becomes 2 or 1 columns as the container shrinks and items wrap — the percentage is really "columns per row" in disguise.
calc() is often layered on top (e.g. flex-basis: calc(33.33% - 10px)) to account for gaps.
- Accepted values:
- flex-basis: 33.333% — three per row
- flex-basis: 50% — two per row
- flex-wrap: wrap — needed for multiple rows
- gap — reduce basis to account for gaps
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: Percentage-Based flex-basis for Column Counts
<style>
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex-basis: calc(33.33% - 10px);
background: steelblue;
color: white;
padding: 8px;
margin: 4px;
}
</style>
<div class="row">
<div class="col">1</div>
<div class="col" style="background: seagreen;">2</div>
<div class="col" style="background: coral;">3</div>
</div>
min-width as a Wrap Trigger
Instead of a fixed percentage, giving items a min-width (e.g. min-width: 200px) alongside flex-grow: 1 lets the browser decide how many fit per row based on available space.
This produces a more naturally responsive grid than a hardcoded percentage, since it adapts to any container width rather than snapping at fixed breakpoints.
- Accepted values:
- min-width: 200px — item never gets narrower
- flex-grow: 1 — items expand into the space
- flex-wrap: wrap — lets items drop to a new line
- flex: 1 1 200px — one-line shorthand
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: min-width as a Wrap Trigger
<style>
.row {
display: flex;
flex-wrap: wrap;
}
.item {
min-width: 200px;
flex-grow: 1;
background: steelblue;
color: white;
padding: 8px;
margin: 4px;
}
</style>
<div class="row">
<div class="item">Adapts to available space</div>
<div class="item" style="background: seagreen;">Adapts to available space</div>
</div>
Combining with Media Queries for Direction Changes
Wrap-based reflow handles size changes gracefully, but sometimes you need a structural change — like switching a sidebar layout from side-by-side to stacked — which requires an actual flex-direction: column override inside a media query.
The rule of thumb: reach for wrap/basis tricks first, and only add a media query when the *direction* itself needs to change, not just the number of columns.
- Accepted values:
- @media (max-width: 600px) — small screens
- flex-direction: column — stacks items
- flex-direction: row — default, side by side
- flex-wrap: wrap — allows wrapping
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: Combining with Media Queries for Direction Changes
<style>
.layout {
display: flex;
gap: 8px;
}
@media (max-width: 600px) {
.layout {
flex-direction: column;
}
}
.layout div {
background: steelblue;
color: white;
padding: 12px;
}
</style>
<div class="layout">
<div>Sidebar</div>
<div style="background: seagreen;">Content</div>
</div>
Common Responsive Flexbox Pitfalls
A frequent mistake is forgetting flex-wrap: wrap entirely and then fighting with overflowing content on narrow screens; another is using flex-basis without flex-shrink: 0 when a fixed minimum size is actually wanted, causing items to shrink below their intended size anyway.
Testing at several widths (not just desktop and one mobile size) catches most of these early.
- Accepted values:
- min-width: 0 — lets items shrink below content size
- flex-wrap: wrap — allows wrapping
- flex-shrink: 1 — default, items shrink
- overflow: hidden | auto — clips or scrolls long content inside an item
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: Common Responsive Flexbox Pitfalls
<style>
.row {
display: flex;
flex-wrap: wrap;
}
.item {
flex-basis: 200px;
flex-shrink: 0;
}
</style>
<div class="row">
<div class="item">Stays at its intended 200px size</div>
</div>
- Forgetting
flex-wrap: wrap, so items shrink or overflow instead of moving to a new line. - Using fixed
widthvalues instead offlex-basisandmin-width. - Forgetting the viewport meta tag, so the layout does not respond on phones.
- Flexbox lays out items in a container along one direction.
- Flex container properties and flex item properties control alignment, spacing, and sizing.
- Flexbox can adapt to different screen sizes.
Unprefixed Flexbox is supported in Chrome 29+, Firefox 28+, Safari 9+ and Edge 12+. Flexbox gap is supported in Chrome 84+, Firefox 63+ and Safari 14.1+.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: