CSS Flexbox
Flexbox (Flexible Box Layout) is a one-dimensional layout model designed for distributing space and aligning items along a single axis — either horizontally or vertically. Unlike CSS Grid which manages two axes simultaneously, Flexbox excels at dynamic layouts where content size is unknown or flexible.
Use Flexbox when you need to align items in a row or column, distribute space dynamically, or center content. It is ideal for navigation bars, card rows, toolbars, and any layout where items need to flex and adapt to available space.
| 1 | .container { |
| 2 | display: flex; |
| 3 | justify-content: space-between; |
| 4 | align-items: center; |
| 5 | gap: 16px; |
| 6 | } |
The common question is not which is better, but which is appropriate for your layout goal.
| Scenario | Recommended | Why |
|---|---|---|
| Navigation bar | Flexbox | One-dimensional row alignment |
| Card grid | Grid | Two-dimensional row/column control |
| Centering a modal | Flexbox | Simple centering on either axis |
| Holy grail page layout | Grid | Named areas and two-axis control |
| Toolbar with wrapping | Flexbox | Flex-wrap and dynamic sizing |
| Masonry / magazine layout | Grid | Explicit placement across rows/columns |
The flex container establishes the flex formatting context. All direct children become flex items arranged along the main axis.
display: flex
| 1 | .container { |
| 2 | display: flex; /* block-level flex container */ |
| 3 | display: inline-flex; /* inline-level flex container */ |
| 4 | } |
flex-direction
Defines the main axis direction — either row (default) or column, and optionally reversed.
| 1 | .row { |
| 2 | flex-direction: row; /* left to right (default) */ |
| 3 | flex-direction: row-reverse; /* right to left */ |
| 4 | } |
| 5 | |
| 6 | .column { |
| 7 | flex-direction: column; /* top to bottom */ |
| 8 | flex-direction: column-reverse; /* bottom to top */ |
| 9 | } |
flex-wrap
Controls whether flex items wrap onto multiple lines when they exceed the container width.
| 1 | .container { |
| 2 | flex-wrap: nowrap; /* default — all items on one line */ |
| 3 | flex-wrap: wrap; /* items wrap as needed */ |
| 4 | flex-wrap: wrap-reverse; /* wrap in reverse direction */ |
| 5 | } |
justify-content
Aligns flex items along the main axis. This is the primary property for distributing space in a flex container.
| 1 | .container { |
| 2 | justify-content: flex-start; /* default — packed at start */ |
| 3 | justify-content: flex-end; /* packed at end */ |
| 4 | justify-content: center; /* centered */ |
| 5 | justify-content: space-between; /* first at start, last at end, equal gaps */ |
| 6 | justify-content: space-around; /* equal space around each item */ |
| 7 | justify-content: space-evenly; /* equal space everywhere */ |
| 8 | } |
align-items
Aligns flex items along the cross axis. The default is stretch, making all items the same height.
| 1 | .container { |
| 2 | align-items: stretch; /* default — items fill cross-axis space */ |
| 3 | align-items: flex-start;/* packed at start of cross axis */ |
| 4 | align-items: flex-end; /* packed at end of cross axis */ |
| 5 | align-items: center; /* centered on cross axis */ |
| 6 | align-items: baseline; /* aligned to text baseline */ |
| 7 | } |
align-content
Aligns wrapped flex lines along the cross axis. Only applies when there are multiple lines (flex-wrap is active).
| 1 | .container { |
| 2 | align-content: stretch; /* default */ |
| 3 | align-content: flex-start; |
| 4 | align-content: flex-end; |
| 5 | align-content: center; |
| 6 | align-content: space-between; |
| 7 | align-content: space-around; |
| 8 | align-content: space-evenly; |
| 9 | } |
gap
Creates gaps between flex items. Unlike margins, gap does not add space before the first or after the last item.
| 1 | .container { |
| 2 | gap: 16px; /* row-gap and column-gap */ |
| 3 | row-gap: 24px; /* vertical gap in wrapped layouts */ |
| 4 | column-gap: 12px; /* horizontal gap */ |
| 5 | } |
Flex items can control their growth, shrinkage, initial size, and alignment independently of other items.
flex-grow
Controls how much a flex item grows relative to siblings when there is extra space. Default is 0 (no growth).
| 1 | .item-a { flex-grow: 1; } /* takes 1 share of extra space */ |
| 2 | .item-b { flex-grow: 2; } /* takes 2 shares (double) */ |
| 3 | .item-c { flex-grow: 0; } /* does not grow */ |
flex-shrink
Controls how a flex item shrinks when space is limited. Default is 1 (items shrink equally). Set to 0 to prevent shrinking.
| 1 | .item { flex-shrink: 1; } /* can shrink (default) */ |
| 2 | .item { flex-shrink: 0; } /* cannot shrink */ |
| 3 | .item { flex-shrink: 2; } /* shrinks twice as much */ |
flex-basis
Sets the initial size of a flex item before space is distributed. Can be a length value, percentage, or auto (default).
| 1 | .item { flex-basis: 200px; } /* initial width */ |
| 2 | .item { flex-basis: 50%; } /* half of container */ |
| 3 | .item { flex-basis: auto; } /* based on content (default) */ |
| 4 | .item { flex-basis: 0; } /* equal sizing regardless of content */ |
flex shorthand
The flex shorthand combines flex-grow, flex-shrink, and flex-basis in that order.
| 1 | .item { |
| 2 | flex: 1; /* flex-grow: 1, flex-shrink: 1, flex-basis: 0% */ |
| 3 | flex: 1 0 auto; /* grow: 1, shrink: 0, basis: auto */ |
| 4 | flex: 0 1 200px; /* grow: 0, shrink: 1, basis: 200px */ |
| 5 | flex: none; /* fully inflexible: 0 0 auto */ |
| 6 | } |
| 7 | |
| 8 | /* Common patterns */ |
| 9 | .sidebar { flex: 0 0 250px; } /* fixed 250px sidebar */ |
| 10 | .content { flex: 1 1 0%; } /* fills remaining space */ |
| 11 | .nav-item { flex: 0 1 auto; } /* sized by content, can shrink */ |
align-self
Overrides the container's align-items for a single item.
| 1 | .item { |
| 2 | align-self: auto | flex-start | flex-end | center | baseline | stretch; |
| 3 | } |
order
Controls the visual order of flex items. Items with a lower order value appear first. Default is 0.
| 1 | .first { order: -1; } /* appears first */ |
| 2 | .last { order: 1; } /* appears last } |
| 3 | .normal { order: 0; } /* default order */ |
Understanding the two axes is fundamental to mastering Flexbox. The main axis is determined by flex-direction, and the cross axis runs perpendicular to it.
| flex-direction | Main Axis | Cross Axis | justify-content | align-items |
|---|---|---|---|---|
| row | Horizontal (→) | Vertical (↓) | horizontal alignment | vertical alignment |
| column | Vertical (↓) | Horizontal (→) | vertical alignment | horizontal alignment |
Flexbox alignment involves two sets of properties: one for the main axis (justify-content) and one for the cross axis (align-items, align-content, align-self).
The place-items shorthand sets both align-items and justify-items (though justify-items does not apply to flex containers). Similarly, place-content sets both align-content and justify-content.
| 1 | .container { |
| 2 | display: flex; |
| 3 | |
| 4 | /* Main axis */ |
| 5 | justify-content: center; |
| 6 | |
| 7 | /* Cross axis */ |
| 8 | align-items: center; |
| 9 | |
| 10 | /* Perfect centering — works for single items */ |
| 11 | } |
| 12 | |
| 13 | /* Perfect centering shorthand */ |
| 14 | .center-me { |
| 15 | display: flex; |
| 16 | place-content: center; /* align-content + justify-content */ |
| 17 | } |
Pattern 1: Centering
The simplest and most reliable way to center content both horizontally and vertically.
| 1 | .center { |
| 2 | display: flex; |
| 3 | justify-content: center; |
| 4 | align-items: center; |
| 5 | } |
Pattern 2: Navigation bar
| 1 | .navbar { |
| 2 | display: flex; |
| 3 | align-items: center; |
| 4 | justify-content: space-between; |
| 5 | padding: 12px 24px; |
| 6 | gap: 24px; |
| 7 | } |
| 8 | |
| 9 | .nav-links { |
| 10 | display: flex; |
| 11 | gap: 16px; |
| 12 | list-style: none; |
| 13 | } |
Pattern 3: Card row with equal height
| 1 | .card-row { |
| 2 | display: flex; |
| 3 | gap: 24px; |
| 4 | flex-wrap: wrap; |
| 5 | } |
| 6 | |
| 7 | .card { |
| 8 | flex: 1 1 280px; |
| 9 | display: flex; |
| 10 | flex-direction: column; |
| 11 | } |
| 12 | |
| 13 | .card-footer { |
| 14 | margin-top: auto; /* pushes footer to bottom */ |
| 15 | } |
Pattern 4: Sticky footer
| 1 | .page { |
| 2 | display: flex; |
| 3 | flex-direction: column; |
| 4 | min-height: 100vh; |
| 5 | } |
| 6 | |
| 7 | .content { |
| 8 | flex: 1; /* grows to fill space, pushing footer down */ |
| 9 | } |
| 10 | |
| 11 | .footer { |
| 12 | flex-shrink: 0; |
| 13 | } |
Pattern 5: Media object
| 1 | .media { |
| 2 | display: flex; |
| 3 | gap: 16px; |
| 4 | align-items: flex-start; |
| 5 | } |
| 6 | |
| 7 | .media-figure { |
| 8 | flex-shrink: 0; |
| 9 | } |
| 10 | |
| 11 | .media-body { |
| 12 | flex: 1; |
| 13 | } |
| Aspect | Flexbox | Grid |
|---|---|---|
| Dimensionality | One-dimensional (row OR column) | Two-dimensional (rows AND columns) |
| Content vs Layout | Content-first — items size based on content | Layout-first — define tracks, place items into cells |
| Item placement | Automatic along main axis | Explicit line-based or named areas |
| Wrapping | flex-wrap creates new lines | Inherently wraps via track definitions |
| Overlap | Not designed for overlap | Items can overlap via grid placement |
| Alignment control | Main axis + cross axis | Two-axis alignment + content distribution |
| Browser support | ✓ All modern browsers | ✓ All modern browsers |
| Best for | Navbars, toolbars, centering, media objects, card rows | Page layouts, dashboards, galleries, magazine layouts |
info
best practice
| Browser | Support | Version |
|---|---|---|
| Chrome | ✓ | 29+ |
| Firefox | ✓ | 22+ |
| Safari | ✓ | 9+ |
| Edge | ✓ | 12+ |
Community
Get help on Slack, Discord or VIP
Stuck on a guide? Join the community and ask.