gap is the flex property you keep forgetting
A Berlin frontend lead sent me a pull request review last year with exactly one line of feedback: “you have reinvented gap.” The offending code was a :not(:last-child) { margin-right: 16px } dance I had written from muscle memory. She was right. That pattern has been unnecessary since 2021 and most of us have not fully noticed.
When gap arrived in flex
CSS gap originated in Grid (CSS Grid Layout Module Level 1, W3C Candidate Recommendation, 2017) as grid-gap, then renamed to plain gap. Flexbox support shipped in Firefox 63 (October 2018), Chrome 84 (July 2020), and Safari 14.1 (April 2021). Caniuse.com records baseline availability at April 2021; the CSS Box Alignment Module Level 3 spec defines gap as applicable to any alignment container, which now includes flex.
What it replaces
Three anti-patterns disappear: (1) margin-right on every child plus :last-child { margin-right: 0 }; (2) negative margins on the container to cancel outer child margins; (3) lobotomised-owl selectors (> * + *) popularised by Heydon Pickering, Inclusive Components, Smashing, 2018, ch. 1. Each was a valid solution to a real problem, and each is now one declaration.
The two-value form
gap: 8px 16px sets row-gap and column-gap independently. Row comes first — same order as border-radius and margin. For a flex container with flex-wrap: wrap, the first value controls the space between wrapped rows, the second between items in a row. For flex-direction: column, swap that mental model.
Why designers like it
Because it maps to how Figma measures space. Adam Argyle's web.dev article “Flexbox 2022” (Google, July 2022) makes the point that design-tool spacing tokens are container-level, not child-level, and gap is the first CSS primitive that agrees. The mental model collapses one level of indirection.
The edge case to remember
Gap only applies between items, not between an item and the container edge — that is still padding. This is intentional and follows the Grid behaviour. If you find yourself writing padding: 16px and gap: 16px on the same container, that is usually correct, not redundant.