kota's memex
.stack {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: var(--flow-space, 1em);
}
<div class="stack">
  <div><!-- child --></div>
  <div><!-- child --></div>
  <div><!-- etc --></div>
</div>

layout

Flow elements require white space to physically and conceptually seperate them from the elements coming before and after them. This is the main purpose of the margin property.

However, design systems concieve elements and components in isolation. At the time of conception, it is not settled whether there will be surrounding content or what the nature of that content will be. One element or component is likely to appead in different contexts, and the requirement for spacing will differ.

We are in the habbit of styling elements, or classes of elements, directly: we make style declarations belong to elements. Typically, this does not produce any issues, but margin is really a property of the relationship between two proximate elements. The following code is therefore problematic:

p {
  margin-bottom: 1.5rem;
}

Since the declaration is not context sensitive, any correct application of the margin is a matter of luck. If the paragraph is proceeded by another element, the effect is desireable. But a :last-child paragraph produces a redundant margin. Inside a padded parent element, this redundant margin combines with the parent's padding to produce double the intended space. This is just one problem with this approach.

The trick it to style the context, not the individual element(s):

.stack {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: var(--flow-space, 1em);
}

flow-space

If --flow-space is defined, it uses that, or defaults to 1em, which is relative to the elements font size.

This is the magic, when you're using a type scale, 1em has a lot of value. It means we get some nice rhythm, just by dropping in our CSS. We can inscrease the space on top of headings and block qoutes like this:

:is(h1, h2, h3, blockquote) {
  --flow-space: 1.5em;
}

:is(h1, h2, h3) + * {
  --flow-space: 0.5em;
}