Main axis, cross axis — the mental model
Everything in flexbox hinges on two axes. flex-direction sets the main axis (horizontal for row, vertical for column); the cross axis runs perpendicular. Then:
justify-contentaligns items along the main axis.align-itemsaligns them along the cross axis.
Flip flex-direction to column and those two properties swap which visual direction they control — the single most common source of “why is my justify-content doing nothing vertically?” confusion. Internalize the axes and the properties stop feeling arbitrary.
The min-width: auto overflow trap
The flexbox gotcha that breaks real layouts: a flex item’s default minimum size is auto, meaning its content’s size. So an item containing a long unbroken string, a <pre> block, or a nested flex layout refuses to shrink below its content width and overflows the container — often blowing out the whole page on narrow screens. The fix is explicit:
.flex-item { min-width: 0; } /* allow it to shrink past content size */
Add min-width: 0 (or overflow: hidden) to flex children that hold potentially wide content. This one line resolves a huge share of mysterious flexbox overflow bugs, especially in nested structures.
gap, and when align-content does nothing
Modern flexbox supports gap for spacing between items — cleaner than margins, with no edge-margin cleanup. One more pitfall: align-content only affects multi-line containers. If your flex container is single-line (flex-wrap: nowrap, the default), align-content is silently ignored — you need flex-wrap: wrap for it to take effect. For single-line cross-axis alignment, use align-items instead.
Flexbox or Grid?
Use flexbox for one-dimensional layouts — a row of buttons, a navbar, centering content, distributing items along a line. Use CSS Grid for two-dimensional layouts where you control rows and columns together. They’re complementary, not competitors; most interfaces use grid for the page skeleton and flexbox inside components. Build your container and item properties with the live preview here, then copy the prefix-free CSS straight into your stylesheet.