Design FIELD NOTES · 4 MIN READ
CSS Flexbox: The Container Properties That Matter
flex-direction, justify-content, align-items, flex-wrap and gap — how the flex container actually positions its items.
Flexbox confuses people for one reason: it has two coordinate systems pretending to be one. Items flow along a main axis and are aligned on a cross axis, and which property moves things left-right versus up-down depends entirely on the direction you chose. Master that swap and the five container properties stop being a cheat sheet and start being obvious.
display: flex changes what the children are
Setting display: flex on an element makes it a flex container and turns its direct children into flex items — block-level behavior for them disappears, margins stop collapsing, and they line up on one line by default. The container is the only thing the five famous properties apply to; the items are shaped by flex-grow, flex-shrink, and flex-basis, which is the other half of the model and a topic of its own.
flex-direction: the axis switch
flex-direction picks which way items flow: row (the default) lays them left to right, column stacks them top to bottom, and the -reverse variants reverse the flow within the same axis. The direction defines the main axis — everything else keys off it. A practical consequence: with row-reverse or column-reverse, visual order and DOM order diverge, which screen readers still follow in DOM order — so reverse the flow only when the reading order stays sensible.
justify-content: distributing along the main axis
justify-content answers "what happens to the free space along the flow direction?". flex-start (the default) packs items at the start and dumps all free space at the end; center splits the space around the group; space-between pushes the leftovers into the gaps between items; space-around gives every item half a gap on each side; space-evenly makes all gaps identical. None of these change item sizes — they only position the group and the spaces around it.
display: flex;
justify-content: space-between; /* first flush left, last flush right */
The classic navigation bar is exactly this: logo at the start, links distributed, last item flush with the far edge.
align-items: the cross-axis behavior
align-items positions items on the cross axis, and its default is the one people never realize they are using: stretch. Items without an explicit cross-axis size grow to fill the container — which is why flexbox equalizes card heights for free in a row. center is the famous one (true vertical centering with two lines of CSS), flex-start and flex-end pack to the cross-axis edges, and baseline aligns items by the baseline of their first line of text, which is what you want when mixing headings and buttons on one row.
Here is the swap in action: with flex-direction: row, justify-content moves items horizontally and align-items vertically; with column, the roles reverse. When a layout "does nothing" after you tweak a property, check the direction first — you are probably pushing along the axis you were not looking at.
flex-wrap and the gap between items
By default (nowrap) items refuse to leave one line and will shrink to fit. wrap lets them spill onto new lines, which turns the container into a de facto multi-row layout — and makes align-content relevant, since it distributes the rows themselves when there is cross-axis space to spare.
For spacing, gap is the modern answer: gap: 12px puts exactly 12px between items and nothing at the container's edges. Margins require :last-child cleanup and misbehave when wrapping starts new rows; gap handles both axes at once and survives reordering, filtering, and responsive item counts untouched.
The minimal declaration habit
Four of the five properties have CSS initial values — row, flex-start, stretch, nowrap — so a container that omits them renders identically to one that writes them out. Writing only the deltas keeps stylesheets reviewable: display: flex; justify-content: space-between; gap: 12px; is a complete navbar container. Emit the full set only when the CSS doubles as documentation, and be consistent about which style a codebase uses.
Try it yourself
The CSS Flexbox Generator builds the container block from the five properties, previews the exact declarations on sample boxes, and writes only the non-default lines unless you ask for more. When placement needs rows and columns simultaneously, the CSS Grid Generator owns the track skeleton instead. And when the container also needs depth, the CSS Box Shadow Generator layers the elevation on top.