Andy’s Favorite CSS (Scoped Spacing Between Elements)

Is this:

.stack > * + * {
  margin-block-start: 1.5rem;
}Code language: CSS (css)

It’s essentially a scoped lobotomized owl. Love it. The idea of putting spacing only between elements is great. Having to select and remove spacing from the last element, or intentionally not select the first element, is weird mental overhead that is nice to avoid. Not that this strange-looking selector is without a bit of weird mental overhead as well, alas.


You don’t generally need to worry about CSS selector performance. Until you do. Super DOM-heavy pages that recalculate layout a lot are the culprit here. Think thousands or tens-of-thousands of nodes. The universal selector (*) is a rough one when you actually are faced with CSS performance. See the recent article The truth about CSS selector performance from Patrick Brosset, in which refactoring some gnarly selectors increased recalc performance some 66%.

This alternative uses one less of them, so you could buy a little time back:

.stack > *:not(:first-child) {
  margin-block-start: 1.5rem;
}Code language: CSS (css)

I would never avoid the owl-based this approach just for theoretical future CSS performance problems, though. If you were in that position, it’s easy enough to refactor to using another technique. Or just being like, oh well, there is a little space on the last element, big shrugging deal.

I often think about Adam’s CSS prediction for 2020:

 I foresee in 2020 that gap will become the primary way we space on the web.

Will gap eat margin? The gap property does just what Andy’s favorite selector is doing: putting spacing between elements only. So the lines become:

.stack {
  display: grid;
  gap: 1em;
}Code language: CSS (css)

In order to take advantage of the gap, you’ve got to use grid or flexbox, which… is a decent-sized ask. This crossed Andy’s mind as well. He says:

… in order to use gap, we would have to make The Stack, either a flex or grid parent. This could cause all sorts of problems for people that grabbed the layout and dropped it in existing projects.

Even when it’s just me working on a site, I still can’t get over my hangup of feeling it’s too weird to make a stack of “regular content”, like <p>s, and <img>s and whatnot, into display: grid;. I’m just scared there are too many side effects like margins sneaking back in and screwing up the spacing, floats not working, one-off gap resizes not possible, and the like.

Future CSS has an answer for this as well! I honestly didn’t see this one coming! And zero browser supports this so don’t hold your breath just yet. But here it is: margin-trim.

To replicate what we’ve been doing here, it turns into:

.stack > * {
  margin-block-start: 1.5rem;
.stack {
  margin-trim: block-start;
}Code language: CSS (css)

The margin-trim property is designed to pluck the margin off of the child element in the implied direction. So in this case, even though that first block puts starting block margin on all elements, the second block takes it off the first element.


I work on CodePen! I'd highly suggest you have a PRO account on CodePen, as it buys you private Pens, media uploads, realtime collaboration, and more.

Get CodePen Pro

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to Top ⬆️