Flexbox has two axes. With flex-direction: row, the main axis runs horizontally and the cross axis runs vertically. justify-content distributes space along the main axis; align-items positions (or stretches) each item along the cross axis. Confusing the two explains most "why won't this align" moments — switching to flex-direction: column swaps their roles entirely.
align-items defaults to stretch: an item with no explicit height fills the whole cross axis, and only shrinks to its natural size once you give it one (or pick center/flex-start/etc). That's why the chips below have different content (different numbers of lines) — so the stretch-vs-not difference is actually visible instead of theoretical.
justify-content also splits into space-between (flush ends, even gaps between), space-around (even space on both sides of each item, so edges get half as much as gaps) and space-evenly (edges get a full share too). The three only differ in how much space lands at the very edges, which is why they're hard to tell apart unless you compare them side by side.
When to use
For a single row or column, these two properties are the first thing to check. Once items wrap onto multiple lines, the gap between lines is align-content's job, not align-items'.