CSS Flexbox Cheatsheet - Flexbox Layout Reference
For developers who have fought with floats or inline-block for centering and equal-width rows. Flexbox is the modern way to lay out a single row or column quickly. The recurring confusion is that Flexbox is one-dimensional and that justify-content and align-items act on different axes. By the end you can center anything, build a toolbar and a wrapping card row, and control item sizing with flex-grow/flex-shrink/flex-basis without trial and error.
Typical Use Case
For front-end developers doing layout work who would rather not fight float or absolute positioning again. Almost all of the difficulty in Flexbox lives in one distinction: flex-direction sets the main axis, align-items acts on the cross axis, so flip the main axis and alignment flips with it. Container properties, main-axis distribution, cross-axis alignment and item-level flex shorthand sit in separate layers, followed by ready-made combinations for centring, sticky footers and responsive card grids, and why flex: 1 is not 1 1 auto.
Container Properties 8
display: flexdisplay: inline-flexflex-direction: rowflex-direction: columnflex-direction: row-reverseflex-direction: column-reverseflex-wrap: wrapflex-flow: row wrapGap & Main-axis Alignment 8
gap: 16pxrow-gap: 16pxcolumn-gap: 16pxjustify-content: flex-startjustify-content: centerjustify-content: flex-endjustify-content: space-betweenjustify-content: space-aroundCross-axis Alignment 7
justify-content: space-evenlyalign-items: stretchalign-items: flex-startalign-items: centeralign-items: flex-endalign-items: baselinealign-content: centerItem Properties 10
flex-grow: 1flex-shrink: 1flex-basis: 200pxflex: 1flex: 0 0 200pxflex: autoflex: nonealign-self: flex-endorder: 1order: -1Common Patterns 6
justify-content: center; align-items: centerjustify-content: space-betweenflex: 1margin-left: automin-height: 100vhflex: 1 0 autoResponsive Tips 5
flex-wrap: wrapflex-basis: 200px; flex-grow: 1flex-wrap: wrap-reverse@media (max-width: 768px) { flex-direction: column }flex: 1 1 100%Parameter matrix
| Parameter | Effect | Example |
|---|---|---|
display: flex | Turns on flex layout; the container becomes a block-level box | display: flex |
display: inline-flex | Turns on flex layout; the container participates in inline-level flow | display: inline-flex |
flex-direction: row | Main axis runs horizontally, the default | flex-direction: row |
flex-direction: column | Main axis runs vertically, which makes the cross axis horizontal | flex-direction: column |
flex-direction: row-reverse | Main axis stays horizontal but items are laid out in reverse | flex-direction: row-reverse |
flex-direction: column-reverse | Main axis runs vertically with the item order reversed | flex-direction: column-reverse |
flex-wrap: wrap | Lets items wrap; nowrap, the default, never wraps | flex-wrap: wrap |
flex-wrap: wrap-reverse | Wrapping starts from the cross-axis end rather than the start | flex-wrap: wrap-reverse |
flex-flow: row wrap | Shorthand that sets flex-direction and flex-wrap together | flex-flow: row wrap |
gap / row-gap / column-gap | Spacing between items, controllable per axis | gap: 16px |
justify-content: flex-start | Packs items at the main-axis start, the default | justify-content: flex-start |
justify-content: center | Centres items along the main axis | justify-content: center |
justify-content: flex-end | Packs items at the main-axis end | justify-content: flex-end |
justify-content: space-between | Flush at both ends, with the slack split between the items | justify-content: space-between |
justify-content: space-around | Equal space around every item, leaving less at the two ends | justify-content: space-around |
justify-content: space-evenly | Every gap is exactly equal, the two outer ones included | justify-content: space-evenly |
align-items: stretch | Stretches items to fill the cross axis, the default | align-items: stretch |
align-items: center | Centres items on the cross axis | align-items: center |
align-items: baseline | Aligns items by their text baseline | align-items: baseline |
align-content: center | Distributes whole lines along the cross axis; only meaningful once wrapping is on | align-content: center |
flex-grow | Growth factor, where 0 disables growing | flex-grow: 1 |
flex-shrink | Shrink factor, whose default of 1 allows items to compress | flex-shrink: 1 |
flex-shrink: 0 | Forbids compression and holds the base size | flex: 0 0 200px |
flex-basis: 200px | Initial main-axis size before the free space is distributed | flex-basis: 200px |
flex: 1 | Shorthand for 1 1 0%, splitting the free space evenly | flex: 1 |
flex: 0 0 200px | Shorthand for neither growing nor shrinking, pinned at 200px | flex: 0 0 200px |
flex: auto | Shorthand for 1 1 auto, which distributes space on top of the content size | flex: auto |
flex: none | Shorthand for 0 0 auto, no flexing whatsoever | flex: none |
flex: 1 1 100% | Takes a full basis so the item fills the line and forces the next one onto a new row | flex: 1 1 100% |
flex: 1 0 auto | A fixed basis with shrinking switched off, the usual sidebar recipe | flex: 1 0 auto |
align-self | Overrides the container's align-items for one item only | align-self: flex-end |
order | Visual placement order; it defaults to 0 and may be negative | order: -1 |
margin-left: auto | Uses margin to push the item to the main-axis end | margin-left: auto |
min-height: 100vh | Combines with a column container and flex: 1 to pin the footer to the bottom | min-height: 100vh |
@media (max-width: 768px) { flex-direction: column } | Flips a horizontal layout into a vertical one on narrow screens | @media (max-width: 768px) { flex-direction: column } |
Common pitfalls
SymptomThe parent says flex: 1 yet the child is squashed flat, so content overflows or the height collapses.
Causeflex: 1 means 1 1 0%, and that shrink factor of 1 lets the item compress below its content size; a vertical main area with no explicit basis simply gets squeezed out.
FixUse flex: 1 0 auto when the item must not compress, or pair flex-grow: 1 on the child with min-height: 100vh on the parent for the vertical case.
Symptomalign-items is on the container, yet nothing looks horizontally centred.
CauseThe container is a column, so the main axis became vertical and the cross axis is now horizontal; align-items controls exactly that axis, while you meant the vertical one.
FixIn a column container use justify-content: center for vertical centring, and in a row container use align-items: center for the same job.
SymptomIn a wrapping flex container the lines clump together and justify-content has no effect on them.
Causejustify-content distributes items along the main axis; where the lines sit as a whole is align-content job.
FixGive the container an align-content value such as center, and confirm flex-wrap: wrap is actually in effect.
Symptomflex-direction and gap were added to an item and nothing whatsoever happened.
CauseThose properties belong to the container but were written on the child; an item only accepts flex, flex-basis, align-self, order and similar item-level properties.
FixMove flex-direction, flex-wrap, gap and justify-content onto the parent and leave the child with flex and align-self.
SymptomAfter reordering with order, Tab focus no longer follows the visual order.
Causeorder changes only the visual placement; the DOM and focus order are untouched, so screen readers and keyboard navigation still follow document order.
FixSort in the DOM itself instead of faking it with order, and if you must use it, check keyboard reachability.
Symptomflex-wrap: wrap plus flex-basis does not wrap: cards get squashed as the window narrows.
CauseAn item min-width defaults to auto, so long content forbids compressing below its own width and the container never sees a reason to wrap.
FixAdd min-width: 0 to the card, or a content-appropriate minimum, so flex-basis can actually drive the wrapping.
SymptomThe footer is not pinned and on a short page the whole document collapses.
CauseOnly the footer got margin-top: auto, but the parent is not a flex container or has no min-height.
FixGive the parent display: flex; flex-direction: column; min-height: 100vh and let the main region carry flex: 1.
Troubleshooting
1Confirm the container really entered flex layout
display: flexIf children still lay out as ordinary blocks, the declaration never reached the real parent, so check that the selector matches.
2Use justify-content to confirm main-axis centring
justify-content: center; align-items: centerBoth together centre horizontally and vertically, but only after you know whether flex-direction is row or column.
3Verify that wrapping takes effect
flex-wrap: wrap; flex-basis: 200px; flex-grow: 1This set of values forms a responsive card grid: a 200px basis, growing when there is room and wrapping when there is not.
4The full container recipe for a sticky footer
display: flex; flex-direction: column; min-height: 100vhAdd flex: 1 to the main region so the footer is pushed to the bottom even on a short page.
5Switch to a single column on narrow screens
@media (max-width: 768px) { flex-direction: column }At 768px and below the main axis turns vertical, stacking what was side by side.
6Override alignment for a single item
align-self: flex-endUseful for pushing one button to the end inside a container that otherwise centres everything.
Command Examples
Center on both axes
.box {
display: flex;
justify-content: center;
align-items: center;
height: 240px;
}justify-content works along the main axis and align-items along the cross axis. With only display: flex everything piles into the top-left corner, which reads as the stylesheet not loading at all.
Two-ended navbar with one item pushed to the end
.nav {
display: flex;
align-items: center;
justify-content: space-between;
}
.nav .logout {
margin-left: auto;
}space-between behaves like flex-end with exactly two children, but redistributes as soon as the child count changes. Use gap or margin-left: auto so the spacing is not hostage to the DOM structure.
Responsive card grid: wrap with a basis and grow
.grid {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.grid > .card {
flex: 1 1 200px;
}
@media (max-width: 768px) {
.grid { flex-direction: column; }
}flex: 1 1 200px uses 200px as the basis and allows growth and shrink, wrapping once the container runs out of width — replacing most hand-written percentage breakpoints.
Sticky footer: the content area grows with flex: 1
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main { flex: 1; }flex: 1 really means 1 1 0%: the item is computed at zero and then given all leftover space, which is what keeps the footer pinned to the viewport bottom instead of floating mid-page under short content.
Reorder visually with order and lay out wrapped lines
.grid {
display: flex;
flex-wrap: wrap;
align-content: center;
gap: 8px;
}
.grid .featured { order: -1; }order changes visual sequence only, not DOM or tab sequence. Treating it as the accessibility fix leaves keyboard and screen-reader users reading in the wrong order.
Common Pitfalls
- Flex items default to min-width: auto, so a long URL, a nowrap code block, or a table can blow out the container and refuse to shrink — an inexplicable horizontal scrollbar. Add min-width: 0 to let inner text ellipsize or wrap.
- flex: 1 means 1 1 0%, not "split the content width". It lays out differently from flex: 1 1 auto whenever a content basis exists, so switching auto to 0% visibly shifts elements that used to line up.
- After flex-wrap: wrap, the default align-content: stretch spreads the lines across the container height, which looks like margin being ignored. Set align-content: flex-start for tight row spacing.
- Mixing margin and gap on the same axis stacks two mechanisms, and margin does not participate in leftover-space distribution — hence a mysterious extra gap after the last item. Pick one per axis.
- A flex container establishes a new formatting context, so position: absolute children are contained by the container, not the viewport. Dropdowns and popovers that rely on viewport positioning jump once moved inside.
- overflow: hidden on the flex container only clips what spills out; the container still sizes to its content minimum, so the parent layout is still pushed. Constrain the items with min-width/min-height instead.
Tips
- flex: 1 is shorthand for flex: 1 1 0% — it divides the remaining space equally.
- align-items aligns on the cross axis; with flex-direction: column the cross axis becomes horizontal.
- The gap property replaces the old margin trick, setting item spacing more cleanly.
- flex-wrap: wrap combined with flex-basis enables responsive grid-like layouts.
- Prefer the flex shorthand; setting flex-grow/shrink/basis separately easily overrides intended behavior.
FAQ
What does flex: 1 actually expand to, and why does it eat up the leftover space?
flex: 1 is shorthand for flex: 1 1 0%, the three numbers being flex-grow, flex-shrink and flex-basis. Because flex-basis is 0%, the item starts at zero size, so the container treats the entire main-axis space as free space and hands it out in the grow ratio 1:1 — hence the equal-width look. Compare flex: auto (1 1 auto), which keeps the content intrinsic size so short items look narrower, and flex: 0 0 200px, which opts out of growing and shrinking entirely and pins the item at 200px.
Why does my container collapse to content height after I set align-items: center?
Because align-items controls the cross axis, and which axis is cross is decided by flex-direction. With the default flex-direction: row the cross axis is vertical, so align-items: center sizes each item to its content and centers it, collapsing the container to the tallest child. The default align-items: stretch is what makes items fill the container height. A related trap: under flex-direction: column the cross axis is horizontal, so align-items: center centers horizontally and vertical centering requires justify-content: center.
How do I make a card list reflow into a responsive grid without any media query?
The trick is flex-wrap: wrap plus flex-basis. Set the container to display: flex; flex-wrap: wrap; gap: 16px and give each card flex: 1 1 200px — flex-basis: 200px supplies the ideal width, flex-grow: 1 lets the cards on a line stretch to fill the row, and flex-shrink: 1 allows them to compress. On a wide viewport they fill one stretched row; once the viewport can no longer fit 200px, they wrap to the next line, giving you a responsive grid with zero @media rules.
How do space-between, space-around and space-evenly differ visually?
All three are justify-content values distributing leftover main-axis space, but they divide it differently. space-between pins the first and last item to the edges and splits the rest evenly — the classic navbar distribution. space-around gives every item equal spacing on both sides, so the outer margins are half the interior gaps. space-evenly makes every gap identical, including the gaps at the container edges. When a card row or button group looks like its edge padding does not match the inner spacing, switching among these three is the fix.
How do I build a sticky footer that sits at the bottom only when content is short?
Give the outer wrapper display: flex; flex-direction: column; min-height: 100vh so the main axis becomes vertical, then set the main content area to flex: 1 — its flex-grow consumes all leftover height and pushes the footer to the bottom. When content exceeds one viewport the wrapper simply grows and the footer follows the content instead of overlapping it. If the footer gets squashed because flex-shrink applies, give the content area flex: 1 0 auto so it keeps its base size and is not compressed.
Official References
Each command links to its official documentation below, so you can verify the latest usage and read deeper.
Maintained by LaoHand
Publicly updated on Jul 21, 2026, continuously proofread against official docs.
Contact Us
Wrong command or description? Send us corrections, business inquiries or product feedback by email.
Contact Us