The Core Concept
Flexbox works on a container–item relationship. Apply display: flex to a parent — it becomes the flex container. Its direct children automatically become flex items. Flex properties on the container control how items are distributed; properties on the items control how individual items size and align themselves.
.container {
display: flex; /* turns element into flex container */
/* or: */
display: inline-flex; /* flex container that flows inline */
}
flex-direction – Main Axis
Controls the direction items flow. The main axis is the primary direction; the cross axis is perpendicular to it.
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 */
justify-content – Main Axis Alignment
Distributes space along the main axis (horizontal in row direction).
justify-content: flex-start; /* default — items at start */
justify-content: flex-end; /* items at end */
justify-content: center; /* items centered */
justify-content: space-between; /* first and last at edges, equal gaps between */
justify-content: space-around; /* equal space around each item (half at edges) */
justify-content: space-evenly; /* equal space between all items including edges */
↑ justify-content: space-between
↑ justify-content: center
align-items – Cross Axis Alignment
Aligns items along the cross axis (vertical in row direction). This is how you vertically center things.
align-items: stretch; /* default — items stretch to fill container height */
align-items: flex-start; /* items align to cross-axis start (top) */
align-items: flex-end; /* items align to cross-axis end (bottom) */
align-items: center; /* items centered on cross axis — vertical centering! */
align-items: baseline; /* items aligned by text baseline */
↑ align-items: center (all vertically centered)
flex-wrap
By default, flex items stay on one line even if they overflow. flex-wrap allows wrapping to multiple lines.
flex-wrap: nowrap; /* default — all on one line, may overflow */
flex-wrap: wrap; /* wrap to new lines as needed */
flex-wrap: wrap-reverse; /* wrap, but new lines go upward */
gap – Spacing Between Items
gap sets the space between flex items. Far cleaner than using margins on children.
gap: 16px; /* equal gap rows and columns */
gap: 16px 24px; /* row-gap: 16px, column-gap: 24px */
row-gap: 16px; /* between rows (when wrapping) */
column-gap: 24px; /* between columns */
flex-grow, flex-shrink, flex-basis
These three properties control how individual flex items size themselves relative to available space.
/* flex-grow — how much an item grows to fill extra space */
/* 0 = don't grow (default), 1 = take proportional share */
.item { flex-grow: 0; } /* stays its natural size */
.item { flex-grow: 1; } /* takes available space */
/* Multiple items with different grow values */
.sidebar { flex-grow: 0; width: 250px; } /* fixed width */
.main { flex-grow: 1; } /* fills the rest */
/* flex-shrink — how much to shrink when space is tight */
/* 1 = shrink proportionally (default), 0 = never shrink */
.logo { flex-shrink: 0; } /* logo never shrinks */
/* flex-basis — the initial size before grow/shrink */
.item { flex-basis: 200px; } /* start at 200px, then grow/shrink */
.item { flex-basis: auto; } /* use item's content size (default) */
.item { flex-basis: 0; } /* start at 0, grow proportionally */
/* flex shorthand: grow shrink basis */
.item { flex: 1; } /* grow:1, shrink:1, basis:0 — fills space equally */
.item { flex: 0 0 250px; } /* fixed 250px, no grow or shrink */
.item { flex: 1 1 auto; } /* default flex behavior */
align-self – Per-Item Cross Axis
Override align-items for a single flex item:
.container { display: flex; align-items: center; height: 120px; }
.item-default { /* inherits align-items: center */ }
.item-top { align-self: flex-start; }
.item-bottom { align-self: flex-end; }
.item-stretch { align-self: stretch; }
.item-auto { align-self: auto; } /* use container's align-items */
order – Visual Reordering
/* Default order is 0. Lower values appear first. */
.first { order: -1; } /* moves before all order:0 items */
.last { order: 1; } /* moves after all order:0 items */
/* Reverse order on mobile */
@media (max-width: 768px) {
.sidebar { order: 2; } /* sidebar below main on mobile */
.main { order: 1; } /* main above sidebar */
}
Screen readers and keyboard navigation follow DOM order, not visual order. Using order to reorder elements that matter to reading sequence or focus order creates an accessibility mismatch. Use it only for purely visual reordering where the logical reading order is unaffected.
Real-World Flexbox Patterns
/* 1. Perfect centering (horizontal + vertical) */
.center {
display: flex;
justify-content: center;
align-items: center;
}
/* 2. Navigation bar */
.nav {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 64px;
}
/* 3. Sidebar + main layout */
.page {
display: flex;
gap: 24px;
}
.sidebar { flex: 0 0 260px; }
.main { flex: 1; min-width: 0; } /* min-width: 0 prevents overflow */
/* 4. Card grid (wrapping) */
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.card { flex: 1 1 280px; } /* min 280px, grow to fill */
/* 5. Button group */
.btn-group {
display: inline-flex;
gap: 8px;
align-items: center;
}
/* 6. Push last item to the end */
.header {
display: flex;
align-items: center;
}
.header .spacer { flex: 1; } /* pushes everything after to the right */
/* 7. Responsive column stack */
.columns {
display: flex;
gap: 24px;
}
@media (max-width: 768px) {
.columns { flex-direction: column; }
}
📋 Summary
- display: flex — activates flexbox on the container. Children become flex items.
- flex-direction — row (default) or column. Sets the main axis.
- justify-content — main axis distribution.
center,space-between,space-evenly. - align-items — cross axis alignment.
center= vertical centering in row direction. - flex-wrap: wrap — allows items to wrap to multiple lines.
- gap — space between items. Cleaner than margins.
- flex: 1 — item grows to fill available space equally.
- flex: 0 0 250px — fixed-width item that neither grows nor shrinks.
- align-self — overrides align-items for one specific item.
- order — visual reorder only. DOM order unchanged.
Frequently Asked Questions
Flexbox is one-dimensional — best for laying out items in a single row or column (navigation bars, button groups, card rows, centering). Grid is two-dimensional — best for layouts that have both rows and columns simultaneously (full-page layouts, image galleries, complex dashboards). The practical rule: if you're thinking about rows OR columns, use flex. If you're thinking about rows AND columns at the same time, use grid. They can and should be combined — grid for the overall page, flexbox for components within it.
Apply to the parent: display: flex; align-items: center;. For both horizontal and vertical centering: display: flex; align-items: center; justify-content: center;. The parent must have a height larger than the content for this to be visible. Use min-height: 100vh to make it fill the viewport.
flex: 1 is shorthand for flex-grow: 1; flex-shrink: 1; flex-basis: 0%. The key part is flex-basis: 0 — the item starts at zero width and grows to fill its share of available space. When multiple items all have flex: 1, they split the available space equally. When one has flex: 2 and another flex: 1, the first gets double the space. Compare with flex: auto which uses flex-basis: auto (content size) before distributing remaining space.
A flex item with min-width: auto (the default) won't shrink below its content width. Add min-width: 0 to the overflowing item — this allows it to shrink below its content size. This is especially important for items containing long text, pre-formatted code blocks, or images. The fix is almost always min-width: 0 on the flex item, or overflow: hidden if you want to clip the content.