Flexbox, formally the CSS Flexible Box Layout Module, is a one-dimensional layout model in CSS that arranges child elements along a single axis, either a row or a column, and distributes available space between them. It is activated by setting display: flex or display: inline-flex on a container, which turns its direct children into flex items.
Flexbox solved layout problems that were awkward with floats and inline blocks, such as vertical centering, equal-height items and flexible spacing. It is now supported in all modern browsers and is the standard tool for components such as navigation bars, toolbars, card footers and form rows.
How flexbox distributes space
Flexbox works with two axes. The main axis follows the direction set by flex-direction, and the cross axis runs perpendicular to it. All alignment and sizing properties refer to these axes rather than to fixed horizontal or vertical directions, which also makes flexbox adapt to right-to-left and vertical writing modes.
The layout algorithm first determines each item’s flex basis, its starting size along the main axis. It then compares the sum of the bases with the container size. Positive free space is shared according to flex-grow; negative free space, meaning overflow, is removed according to flex-shrink weighted by each item’s basis.
| Property | Initial value | What it controls |
|---|---|---|
flex-grow | 0 | Share of positive free space the item receives |
flex-shrink | 1 | How strongly the item shrinks when space is short |
flex-basis | auto | Starting size before free space is distributed |
The shorthand flex combines all three. The keyword `flex: 1` means grow 1, shrink 1, basis 0%, which gives items equal widths regardless of content, while flex: auto uses the content size as the basis and therefore produces unequal widths for unequal content.
Container and item properties
Flexbox properties are split between the flex container and the flex items. Container properties define direction, wrapping and group alignment, while item properties adjust individual items.
| Property | Common values | Effect |
|---|---|---|
flex-direction | row, column, row-reverse | Sets the main axis |
flex-wrap | nowrap, wrap | Allows items to form multiple lines |
justify-content | flex-start, center, space-between | Distributes items along the main axis |
align-items | stretch, center, baseline | Aligns items on the cross axis |
align-content | flex-start, space-between | Distributes lines when wrapping |
gap | Length such as 1rem | Sets consistent space between items |
On the item side, align-self overrides cross-axis alignment for one item and order changes the visual position. Auto margins are also powerful: `margin-left: auto` pushes an item to the far end of a row, a common technique for placing a login button at the right of a navigation bar.
Flexbox compared with CSS grid
Flexbox and CSS grid are complementary, not competing. Flexbox is content-out: items determine their size and the container adapts. Grid is layout-in: the container defines tracks and items are placed into them.
| Criterion | Flexbox | CSS grid |
|---|---|---|
| Dimensions | One axis at a time | Rows and columns together |
| Sizing driver | Item content | Container track definitions |
| Alignment across lines | Each wrapped line is independent | Items align to shared tracks |
| Typical use | Toolbars, nav bars, button groups | Page layouts, card galleries, dashboards |
| Overlapping items | Not supported directly | Supported by placing items in the same cells |
A practical rule is to use grid when items must line up in two directions and flexbox when a group of items only needs to flow and align in one direction. Both are often combined, with a grid for the page and flexbox inside its components, and container queries can adjust either one based on the component’s own width.
Typical flexbox patterns
A small set of patterns covers most everyday uses of flexbox in production code.
| Pattern | Key declarations | Result |
|---|---|---|
| Perfect centering | justify-content and align-items set to center | Child centered on both axes |
| Navigation bar | align-items center, gap, auto margin | Links aligned with an item pushed to the end |
| Equal columns | flex: 1 on each item | Columns share width equally |
| Sticky footer | Column direction, flex-grow on main content | Footer stays at the bottom of short pages |
| Wrapping tags | flex-wrap: wrap with gap | Items flow onto new lines as needed |
Pitfalls and common mistakes
Most flexbox problems come from default values that are not obvious. Knowing them prevents a large share of layout bugs.
- Minimum size auto: flex items will not shrink below their content width by default, so long words or wide tables overflow; setting
min-width: 0fixes this. - Visual reordering:
orderand reverse directions change only the visual sequence, not the reading or tab order, which can confuse keyboard and screen reader users. - Grid-like expectations: wrapped flex lines do not align columns across lines; use CSS grid for true columns.
- Margins between items: the
gapproperty is cleaner than margins and avoids extra space at the edges. - Percentage heights in columns: children may not resolve heights as expected unless the container has a definite height.
The minimum size issue is the single most frequent surprise. When text refuses to truncate with an ellipsis inside a flex item, the cause is almost always the automatic minimum width.
A plain-language summary
Flexbox is a way of telling a web browser how to line up a group of elements. They can sit in a row or in a column. Flexbox also decides how the free space is shared between them.
Imagine books on a shelf that can stretch or shrink. You decide whether they sit close together, spread out or stand in the middle. The shelf then adjusts by itself when it gets wider or narrower, for example on a phone screen.
An example from practice
A front-end developer builds the header of an online shop. It contains a logo, a search field, three navigation links and a cart button, and it must work from 320 px phone screens to wide desktop monitors.
The header becomes a flex container with align-items: center and a gap of 1rem. The search field gets flex: 1 so it takes the remaining space, and min-width: 0 lets it shrink on small screens. The cart button receives margin-left: auto to stay at the right edge.
On narrow screens, a media query switches on wrapping so the search field moves to its own line. The result is a header that adapts without fixed widths and needs only a few lines of CSS.