The axes swap, and that is the whole confusion
Flexbox lays items out along one axis and aligns them across the other. Which is which is decided entirely by flex-direction.
In a row, the main axis runs horizontally: justify-content spaces items left to right and align-items positions them vertically. Switch to a column and the two swap over — justify-content now runs down the page and align-items across it.
Nearly every moment of confusion with flexbox traces back to that swap. If a property has stopped doing what you expect, check the direction before anything else. Seeing it happen in the [msm_tool slug="flexbox-generator"] tends to fix it permanently in a way that reading about it does not.
The values worth knowing
justify-content distributes along the main axis. flex-start, center and flex-end are self-explanatory. The three that get confused:
space-between — no space at the ends, so the first and last items touch the edges. This is the one you want for a header with a logo on one side and navigation on the other.
space-around — each item gets equal space on both sides, so the outer gaps end up half the size of the inner ones. It looks slightly wrong and is rarely what anyone meant.
space-evenly — every gap is equal, including the outer ones. Usually what people reach for space-around expecting.
align-items positions across the other axis. stretch is the default and is why a row of cards with different content lengths all end up the same height — useful, and occasionally surprising. center is the one that makes vertical centring trivial, which was famously not the case before flexbox existed.
Centring, finally
justify-content: center and align-items: center together centre on both axes, regardless of direction. That pair is the answer to a problem that consumed an unreasonable amount of collective effort for about fifteen years.
One caveat: the container needs a height for vertical centring to have anywhere to happen. A flex container that is only as tall as its contents centres them in exactly the space they already occupy, which looks like nothing happened.
nowrap is the default, and it squeezes
Items that do not fit are compressed rather than moved to a new line. If a row is crushing its contents on a narrow screen, flex-wrap: wrap is the fix, and it is the single most common omission in flex layouts that break on mobile.
Worth knowing what wrapping changes: once items wrap, align-items applies within each line, and align-content controls how the lines themselves are distributed. That second property only does anything on a wrapped, multi-line container, which is why it appears to be broken when tried on a single line.
gap replaced margins
One declaration on the container instead of a margin on every child, with no leading or trailing space to strip off and no :last-child rule. It is the reason modern flex layouts need far less tidying than they used to, and it is supported everywhere current.
The reverse directions have an accessibility cost
row-reverse and column-reverse change the order items appear in visually. They do not change the order in the document, which is what keyboard navigation and screen readers follow.
Reversing for visual effect leaves those two disagreeing: someone tabbing through the page moves in an order that does not match what they see. The same applies to the order property. Use them where the visual and document order genuinely should differ and you have thought about it — not as a quick way to move something to the right.
flex-grow, flex-shrink and flex-basis
These sit on the children rather than the container, and the shorthand catches people out. flex: 1 means grow to fill, do not resist shrinking, and start from zero — which is why flex: 1 on several items makes them equal width regardless of their content.
If you want items sized by their content but allowed to grow, flex: 1 1 auto is the form. The difference between a basis of 0 and auto accounts for most of the surprise when items come out a different size than expected.
Flexbox or grid
Use flexbox when the content decides the sizes: a navigation bar, a row of buttons, a card's internal layout. Use grid when the layout is defined before the content: a page skeleton, a gallery of equal tiles, anything two-dimensional.
They nest happily and most real pages use both — a grid for the page, flexbox inside each card.