CSS Flexbox Cheat Sheet: Visual Guide to All Properties
Key Takeaways
- • Flexbox is one-dimensional — it controls layout along a single axis at a time (row or column). For two-dimensional control, use Grid.
- • 97% global browser support per Can I Use (May 2026) — no fallbacks needed for any modern target.
- •
min-width: 0is the most important fix you don't know about — it's the solution to 80% of unexpected Flexbox overflow issues. - •
flex: 1shorthand expands toflex-grow: 1; flex-shrink: 1; flex-basis: 0%— the most common source of confusion between explicit and shorthand values. - • The State of CSS 2025 survey shows 78% of developers now use Grid regularly, but Flexbox remains the dominant choice for component-level layout.
It's Monday morning. Your designer drops a Figma link: a navbar with a logo left-aligned, links centered, and a CTA button pinned right. Below it, a card grid where each card has a footer that sticks to the bottom regardless of content height. You have a deadline in two hours.
If you know Flexbox cold, you write that navbar in six lines of CSS. If you don't, you spend ninety minutes on Stack Overflow and still get the footer wrong. This guide is the reference you keep open. Every container property, every item property, the shorthand traps, and the five layout patterns you'll build repeatedly.
According to the State of CSS 2025 survey (conducted by Devographics, ~8,000 developer respondents), Flexbox has 99% awareness and 97% usage — it is the most universally used CSS layout feature. Meanwhile, Can I Use reports 97.1% global browser support as of May 2026. There are no meaningful IE11 concerns for new projects. This is the safe default.
The Mental Model: Main Axis vs Cross Axis
Everything in Flexbox is defined relative to two axes. The main axis is set by flex-direction. The cross axis is perpendicular to it. Every alignment property references one of these axes — confusing them is the #1 source of Flexbox bugs.
/* flex-direction: row (default)
Main axis: horizontal (left → right)
Cross axis: vertical (top → bottom) */
/* flex-direction: column
Main axis: vertical (top → bottom)
Cross axis: horizontal (left → right) */
/* flex-direction: row-reverse
Main axis: horizontal (right → left)
Cross axis: vertical (top → bottom) */
/* The axis rules:
justify-content → controls spacing along MAIN axis
align-items → controls alignment along CROSS axis
align-content → controls MULTIPLE LINES along cross axis (requires flex-wrap)
align-self → overrides align-items for a SINGLE item */Container Properties — The Full Reference
display
.container {
display: flex; /* block-level flex container */
display: inline-flex; /* inline-level flex container — sizes to content */
}
/* flex vs inline-flex:
flex: container takes full line width (like block)
inline-flex: container only as wide as its children (like inline)
Use inline-flex for: button groups, badge rows, tag lists */flex-direction
.container {
flex-direction: row; /* default — left to right */
flex-direction: row-reverse; /* right to left */
flex-direction: column; /* top to bottom */
flex-direction: column-reverse; /* bottom to top */
}
/* Real-world uses:
row: navbar, button group, tag list
column: card layout, sidebar, form fields
column-reverse: "load more" where newest items appear first visually */flex-wrap
.container {
flex-wrap: nowrap; /* default — all items on one line, may overflow */
flex-wrap: wrap; /* items wrap to next line when overflow */
flex-wrap: wrap-reverse; /* items wrap upward instead of downward */
}
/* flex-flow is shorthand for flex-direction + flex-wrap */
.container {
flex-flow: row wrap; /* common responsive pattern */
flex-flow: column nowrap; /* vertical stack, no wrap */
flex-flow: row-reverse wrap; /* right-to-left with wrapping */
}
/* Responsive card grid without media queries: */
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card-grid > * {
flex: 1 1 280px; /* grow/shrink freely, minimum 280px wide */
/* Cards will fit as many per row as possible, wrapping when needed */
}justify-content
.container {
justify-content: flex-start; /* default — items packed to start */
justify-content: flex-end; /* items packed to end */
justify-content: center; /* items centered */
justify-content: space-between; /* equal gaps BETWEEN items, no outer gaps */
justify-content: space-around; /* equal gaps AROUND each item (half-gaps at edges) */
justify-content: space-evenly; /* equal gaps everywhere including edges */
justify-content: start; /* respects writing mode */
justify-content: end; /* respects writing mode */
}
/* space-between vs space-around vs space-evenly:
3 items in a 300px container:
space-between: |item| gap |item| gap |item| (gaps: 50px each)
space-around: |gap/2|item|gap|item|gap|item|gap/2|
space-evenly: |gap|item|gap|item|gap|item|gap| (all equal: ~43px)
Most common: space-between for navbars, center for modal content */align-items
.container {
align-items: stretch; /* default — items stretch to fill cross axis */
align-items: flex-start; /* items align to start of cross axis */
align-items: flex-end; /* items align to end of cross axis */
align-items: center; /* items centered on cross axis */
align-items: baseline; /* items aligned by text baseline */
}
/* align-items: baseline is underused but powerful:
When items have different font sizes or padding, baseline alignment
makes their text sit on the same horizontal line — perfect for
mixed-size typography in a navbar or header */
/* Perfect centering (both axes): */
.centered-container {
display: flex;
justify-content: center; /* center on main (horizontal) axis */
align-items: center; /* center on cross (vertical) axis */
min-height: 100vh; /* give it height to center within */
}align-content
/* align-content: controls spacing between MULTIPLE ROWS/COLUMNS
Only has effect when flex-wrap: wrap and items span multiple lines */
.container {
align-content: stretch; /* default — rows stretch to fill */
align-content: flex-start; /* rows packed at start */
align-content: flex-end; /* rows packed at end */
align-content: center; /* rows centered in container */
align-content: space-between; /* rows spaced with no outer gap */
align-content: space-around; /* rows spaced with half outer gap */
align-content: space-evenly; /* rows spaced equally */
}
/* align-items vs align-content:
align-items: aligns items within each row individually
align-content: aligns the rows themselves within the container
With only ONE row of items, align-content has no effect.
With MULTIPLE rows, both apply: align-content positions rows,
align-items positions items within each row. */gap
/* gap replaces the old margin hack — use it exclusively */
.container {
gap: 1rem; /* equal gap in both directions */
gap: 1rem 2rem; /* row-gap column-gap */
row-gap: 1rem; /* vertical gap between rows */
column-gap: 2rem; /* horizontal gap between columns */
}
/* The old margin trick (avoid in new code): */
.old-way .item + .item { margin-left: 1rem; }
/* Problem: adds margin to ALL items including last,
or requires :last-child removal hack */
/* gap is clean: no outer margins, works with flex-wrap,
available in Flexbox since Chrome 84, Firefox 63, Safari 14.1
(97%+ global support per Can I Use, May 2026) */Item Properties — The Full Reference
flex-grow, flex-shrink, flex-basis
/* flex-grow: unitless ratio — how much extra space this item takes */
.item { flex-grow: 0; } /* default — don't grow */
.item { flex-grow: 1; } /* take all available space */
/* If item A has grow: 2 and item B has grow: 1,
A gets 2/3 of free space, B gets 1/3 */
/* flex-shrink: unitless ratio — how much this item can shrink */
.item { flex-shrink: 1; } /* default — shrink proportionally */
.item { flex-shrink: 0; } /* never shrink — useful for fixed-size items */
/* flex-shrink: 0 prevents the item from ever being squished */
/* flex-basis: initial size before grow/shrink is applied */
.item { flex-basis: auto; } /* default — use content width/height */
.item { flex-basis: 0; } /* start from zero (used with flex-grow) */
.item { flex-basis: 200px; } /* fixed initial size */
.item { flex-basis: 25%; } /* percentage of container */
/* IMPORTANT: flex-basis vs width:
flex-basis sets the "ideal" size, then grow/shrink modifies it
width also works but flex-basis is preferred in flex containers
(flex-basis takes priority over width in flex contexts) */The flex shorthand — and why it trips everyone up
/* flex: <grow> <shrink> <basis> */
.item { flex: 0 1 auto; } /* default (same as not setting flex at all) */
.item { flex: 1; } /* = flex: 1 1 0% — MOST IMPORTANT: basis is 0%, not auto! */
.item { flex: auto; } /* = flex: 1 1 auto */
.item { flex: none; } /* = flex: 0 0 auto — fixed size, no grow/shrink */
.item { flex: 2; } /* = flex: 2 1 0% */
.item { flex: 0 0 200px; } /* fixed 200px, never grow or shrink */
/* THE KEY DIFFERENCE:
flex: 1 → basis: 0% → items share ALL available space equally
flex: auto → basis: auto → items share REMAINING space (after content sizes) */
/* Example with 3 items in a 300px container:
Item A content: 100px, Item B content: 50px, Item C content: 50px
flex: 1 (basis 0%):
All start at 0, 300px split 1:1:1 → each gets 100px
Result: A=100, B=100, C=100
flex: auto (basis: auto):
Content sizes first: 100 + 50 + 50 = 200px
100px free space, split 1:1:1 → each gets ~33px bonus
Result: A≈133, B≈83, C≈83
Use flex: 1 for equal-width columns.
Use flex: auto for equal-share-of-remaining-space columns. */align-self
/* align-self overrides align-items for a specific item */
.item {
align-self: auto; /* default — inherits from align-items */
align-self: flex-start; /* align to start of cross axis */
align-self: flex-end; /* align to end of cross axis */
align-self: center; /* center on cross axis */
align-self: stretch; /* stretch to fill cross axis */
align-self: baseline; /* align to text baseline */
}
/* Classic use: pin one item to bottom of a flex row */
.navbar {
display: flex;
align-items: center; /* center all items vertically */
}
.navbar .tagline {
align-self: flex-end; /* this one item aligns to bottom */
margin-top: auto; /* alternative: auto margins work too */
}order
/* order: integer — default 0, lower numbers appear first */
.item { order: 0; } /* default */
.item { order: -1; } /* appears before items with order: 0 */
.item { order: 1; } /* appears after items with order: 0 */
/* Use case: mobile-first reordering without JS */
/* On mobile: title first, image second */
/* On desktop: image left, title right */
.product {
display: flex;
flex-direction: column; /* mobile: vertical stack */
}
.product-image { order: 1; }
.product-title { order: 2; }
@media (min-width: 768px) {
.product { flex-direction: row; }
.product-image { order: 2; } /* image moves right on desktop */
.product-title { order: 1; } /* title moves left */
}
/* WARNING: order only changes visual order, not DOM order.
Screen readers and keyboard navigation follow DOM order.
Never use order in a way that creates confusing tab sequences. */All Flexbox Properties at a Glance
| Property | Applies To | Default | Common Values |
|---|---|---|---|
| display | Container | block | flex | inline-flex |
| flex-direction | Container | row | row | column | row-reverse | column-reverse |
| flex-wrap | Container | nowrap | nowrap | wrap | wrap-reverse |
| flex-flow | Container | row nowrap | shorthand for direction + wrap |
| justify-content | Container | flex-start | center | space-between | space-around | space-evenly |
| align-items | Container | stretch | center | flex-start | flex-end | baseline |
| align-content | Container | stretch | center | space-between | flex-start (multi-line only) |
| gap | Container | 0 | 1rem | 1rem 2rem | row-gap | column-gap |
| flex-grow | Item | 0 | 1 | 2 | any positive number |
| flex-shrink | Item | 1 | 0 (no shrink) | 1 | any positive number |
| flex-basis | Item | auto | 0 | 200px | 25% | content |
| flex | Item | 0 1 auto | 1 | auto | none | 0 0 200px |
| align-self | Item | auto | center | flex-start | flex-end | stretch | baseline |
| order | Item | 0 | -1 | 0 | 1 | any integer |
5 Real-World Layout Patterns
1. Navbar: Logo Left, Nav Center, CTA Right
/* HTML:
<nav class="navbar">
<div class="logo">Brand</div>
<ul class="nav-links">...</ul>
<button class="cta">Sign Up</button>
</nav> */
.navbar {
display: flex;
align-items: center;
padding: 0 2rem;
height: 64px;
}
.logo { flex: none; } /* fixed size, doesn't grow */
.nav-links {
flex: 1; /* take remaining space */
display: flex;
justify-content: center; /* center nav links within their space */
gap: 2rem;
list-style: none;
}
.cta { flex: none; } /* fixed size, pinned to right by flex layout */2. Card with Footer Pinned to Bottom
/* The classic problem: cards in a grid have different content lengths
but footers must align at the same vertical position */
.card {
display: flex;
flex-direction: column; /* vertical stack inside card */
height: 100%; /* or a fixed height */
}
.card-body {
flex: 1; /* body grows to fill available space */
/* Footer is pushed to bottom because body takes all the extra space */
}
.card-footer {
flex: none; /* footer stays at its natural height */
margin-top: auto; /* alternative to flex: 1 on body — same result */
}
/* Combined with a grid of cards: */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
align-items: stretch; /* cards stretch to same row height */
}3. Responsive Wrapping Tag List
.tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tag {
flex: none; /* tags don't grow — natural content width */
padding: 0.25rem 0.75rem;
border-radius: 9999px;
white-space: nowrap; /* prevent tag text from wrapping */
}
/* No media queries needed — tags automatically wrap to next line */4. Sidebar + Main Content Layout
.layout {
display: flex;
min-height: 100vh;
}
.sidebar {
flex: 0 0 280px; /* never grow or shrink, always 280px */
position: sticky;
top: 0;
height: 100vh;
overflow-y: auto;
}
.main {
flex: 1; /* take all remaining space */
min-width: 0; /* CRITICAL: prevents overflow when content is wide */
padding: 2rem;
overflow: hidden;
}
/* Mobile: stack vertically */
@media (max-width: 768px) {
.layout { flex-direction: column; }
.sidebar {
flex: none;
position: static;
height: auto;
}
}5. Icon + Text Button Alignment
.btn {
display: inline-flex; /* inline-flex: button sizes to content */
align-items: center; /* vertically center icon and text */
gap: 0.5rem;
padding: 0.75rem 1.25rem;
cursor: pointer;
}
/* Icon and text stay vertically centered even if font-size changes */
/* gap: 0.5rem is cleaner than margin on the icon */
/* Loading state: swap text for spinner without layout shift */
.btn.loading .btn-text { display: none; }
.btn.loading .btn-spinner { display: block; }The min-width: 0 Fix
This is the most important Flexbox tip that doesn't appear in most tutorials. By default, a flex item's minimum size is its min-content size — the smallest it can be without overflowing its own content. This is usually fine, but it means a flex item containing a long word, a wide image, or a pre block will refuse to shrink below that content's width.
/* THE BUG: long text or pre element overflows its flex container */
.sidebar-layout {
display: flex;
}
.main-content {
flex: 1;
/* BUG: if main-content contains a wide <pre> or long URL,
it won't shrink — it'll overflow the flex container */
}
/* THE FIX: min-width: 0 on the flex item */
.main-content {
flex: 1;
min-width: 0; /* allow item to shrink below its content width */
overflow: hidden; /* or overflow: auto — control how overflow is handled */
}
/* Works the same vertically for column layouts: */
.flex-column-item {
flex: 1;
min-height: 0; /* allow item to shrink below its content height */
overflow: auto;
}
/* Real example: code block in flex layout */
.article-layout {
display: flex;
gap: 2rem;
}
.article-body {
flex: 1;
min-width: 0; /* without this, <pre> blocks blow out the layout */
}
.article-sidebar {
flex: 0 0 250px;
}Per the CSS Flexbox specification (W3C CSS Flexible Box Level 1), the minimum size of a flex item is its min-content size by default. Setting min-width: 0 (or min-height: 0 for column layouts) overrides this to zero, letting the item shrink freely and leaving the overflow behavior to you.
Auto Margins: Flexbox's Hidden Superpower
/* In a flex container, margin: auto absorbs ALL available space in that direction */
/* Push last item to the right: */
.navbar { display: flex; align-items: center; gap: 1rem; }
.navbar .login-btn { margin-left: auto; } /* login button pins to right */
/* Center one item horizontally in a column: */
.column { display: flex; flex-direction: column; }
.column .centered { margin: 0 auto; } /* centered horizontally */
/* Push items apart in a vertical layout: */
.card { display: flex; flex-direction: column; }
.card-footer { margin-top: auto; } /* footer pushed to bottom */
/* Space a group of items from another group: */
.toolbar { display: flex; align-items: center; gap: 0.5rem; }
.toolbar .right-group { margin-left: auto; } /* right-aligned group */
/* Auto margins in Flexbox work differently from block layouts:
They consume ALL free space first, THEN justify-content is applied.
This means margin: auto takes priority over justify-content spacing. */Frequently Asked Questions
What is the difference between justify-content and align-items in Flexbox?
justify-content aligns flex items along the main axis (horizontal when flex-direction is row). align-items aligns them along the cross axis (vertical when flex-direction is row). If flex-direction is column, the axes flip: justify-content becomes vertical and align-items becomes horizontal.
What does flex: 1 mean in CSS?
flex: 1 expands to flex-grow: 1; flex-shrink: 1; flex-basis: 0%. The basis of 0% (not auto) means items start from zero before distributing space — so all siblings with flex: 1 share the container equally regardless of their content size. This is subtly different from flex: auto which uses content width as the starting basis.
When should I use Flexbox vs CSS Grid?
Use Flexbox for one-dimensional layouts — a row of nav links, a toolbar, a card's internal layout. Use Grid for two-dimensional layouts where rows and columns must align. The practical test: if you're thinking about aligning items in one direction, use Flexbox. If you're thinking about rows AND columns simultaneously, use Grid.
How do I center a div with Flexbox?
Apply display: flex; justify-content: center; align-items: center; to the parent. This centers children both horizontally and vertically. The parent needs explicit dimensions (height: 100vh or a fixed height) to have space to center within. For centering a single element on the page, min-height: 100vh on the parent works.
What is the difference between align-items and align-self?
align-items is a container property that sets cross-axis alignment for ALL flex items. align-self is an item property that overrides align-items for one specific item. If the container says align-items: center, you can set align-self: flex-start on a single item to pin it to the top while others remain centered.
Why is my Flexbox item not shrinking below its content size?
Flex items won't shrink below their min-content size by default. Add min-width: 0 to the flex item to allow further shrinking. This is the solution to ~80% of unexpected Flexbox overflow bugs — especially when a flex item contains a wide <pre> block, a long URL, or an image with an explicit width.
What does flex-wrap: wrap do?
flex-wrap: wrap allows flex items to wrap to a new line when the container runs out of space. The default nowrap squishes all items into one line. Combined with flex-basis percentages or min-width on items, wrap enables responsive layouts without media queries — items flow to the next line naturally when the container narrows.
Format Your CSS Inline
After writing Flexbox layouts, use BytePane's CSS Formatter to clean up spacing and normalize your code. For the Grid vs Flexbox decision in detail, see the CSS Flexbox vs Grid guide.
Open CSS FormatterRelated Articles
CSS Flexbox vs Grid
Decide which layout system to use with side-by-side examples for navbars, cards, and dashboards.
CSS Grid vs Flexbox Deep Dive
Detailed technical comparison with named grid lines, template areas, and auto-placement.
CSS :has() Selector Guide
The parent selector that changes how you write component-level CSS.
Web Performance Checklist 2026
CSS performance: layout thrashing, containment, and rendering pipeline optimization.