Mind the Flex-gap

Jonathan Schofield
4 min readFeb 19, 2019

--

Some thoughts on bridging the CSS generation gap between the world of Flexbox we have now, with margins on child elements, and Flex layout with gaps defined on the parent container. Along the way there’s poetically responsive media-query-free layout — let down by poor plagiarism of a poetry classic.

Adapted from Gustave Doré’s engraving for the Rime of the Ancient Mariner, depicting sailors on the wooden deck of a ship facing an albatross.

Look Ma, no media queries

Heydon Pickering is a clever chap. If you’re involved in web dev you should follow him. Last month, his latest gift to the CSS world was a kind of Holy Grail, a Flexbox-based component for laying out a group of items responsively without any media queries. He named it his Holy Albatross, a nod to the angst involved until he was able to see the light (I’d still be in the dark on many things if it weren’t for him).

Resizing the viewport width of Heydon’s Flexbox One Column Switch CodePen.

To keep the net effect “looking flush”, Heydon deploys the Fukol approach of margins on the child items, offset by negative margins on the parent container, but acknowledges that:

“This will become redundant when the gap property is more widely supported [in Flex layout mode].”

As Coleridge’s Ancient Mariner might have riffed🤘, when it comes to Flexbox we’ve been promised a lot but not yet quite enough:

“Layout, layout, every where,
Which can grow and shrink;
Layout flexing every where,
But gaps we’ll have to rethink”

The gap generation gap

Right now, if everyone used the latest Firefox, there’d be no rethinking of margins as gaps needed, because since version 63 was released in late October 2018 we can have our layout cake and eat it:

.container {
display: flex;
flex-wrap: wrap;
--modifier: calc(40rem — 100%);
/* Ooh! */
column-gap: 2rem;
row-gap: 2rem;
}
.container > * {
flex-grow: 1;
flex-basis: calc(var(--modifier) * 999);
}
MDN browser compatibility table for column-gap in Flex layout

Unfortunately, right now it’s just Firefox soaring overhead, and there’s no date yet for when the Chromium or Webkit teams will achieve lift-off. Which is a shame, because not only are there roughly 40 to 50 fewer bytes of CSS to write, there’s also less markup if one wants to robustly style the container itself with padding:

A CodePen exploring the use of margins and padding on columnised groups, with and without a wrapper or {row,column]-gap properties.

But there’s another challenge. How can we distinguish…

  1. browsers that cover the expanded spec
  2. from browsers that uphold Flex and Grid layout as originally defined, but not {row,column}-gap in Flex layout mode?

We can’t test for:


@supports (column-gap: 1rem) {
/* styles */
}

…because browsers of types 1 and 2 will both pass.

Rachel Andrew has raised this issue in the broader context of testing support of properties and values with partial implementations.

When it comes to gaps, even though the move is away from layout module specific properties towards un-prefixed ones (for example, grid-column-gap is now well supported as just column-gap), there is still the shorthand:

grid-gap: {row-gap} {column-gap};

So perhaps, as Simon Lawrence has proposed, we could introduce flex-gap to squeeze us through the bars of @supports jail. Then we could have an even more context sensitive albatross:

.container {
display: flex;
flex-wrap: wrap;
/* Stop gap */
--margin: 1rem;
margin: calc(var(--margin) * -1);
}
.container > * {
flex-grow: 1;
flex-basis: calc(var(--modifier) * 999);

/* Stop gap */
margin: var(--margin);
}
/* Generation gap */
@supports (flex-gap: 1rem) {
.container {
flex-gap: 2rem;
}
.container,
.container > * {
margin: auto;
}
}
An albatross soaring, viewed from below.

In other words, until some future nirvana when close to 100% of user agents can reliably be assumed to support gaps applied to Flex parent elements, we could prefix those gaps — and get the layout wingspan we want.

Note that we won’t have to prefix gaps when they are applied to Grid or multi-column elements because the concept of explicit gaps has been intrinsic to those layout modules from the start.

It would be great if there could also be a fully algorithmic solution to asymmetric columns using Grid without resorting to a media query, but I haven’t found one yet.

--

--