At first, there were flexboxes (the children of a display: flex
container). If you wanted them to be visually separate, you had to use content justification (i.e. justify-content: space-between
), margin
trickery, or sometimes, both. Then along came grids (a display: grid
container), and grids could have not-margin not-trickeried minimum gaps between grid cells, thanks to grid-gap
. Flexboxes did not have gaps.
Now they can, thanks to the growing support of gap
, the grid-gap
successor that isn’t confined to grids. With gap
, you can gap your grids, your flexboxes, and even your multiple columns. It’s gaptastic!
Gap with Grid
Let’s start where gap
is the most robust: CSS Grid. Here’s a basic grid setup in HTML and CSS:
<section>
<div>div</div>
<div>div</div>
<div>div</div>
<div>div</div>
<div>div</div>
<div>div</div>
<div>div</div>
</section>
section {
display: grid;
grid-template-rows: repeat(2,auto);
grid-template-columns: repeat(4,auto);
gap: 1em;
}
section div {
width: 2em;
}
That places the grid cells at least 1em
apart from each other. The separation distance can be greater than that, depending on other conditions beyond the scope of this post, but at a minimum they should be separated by 1em
. (OK, let’s do one example: gap
’s gaps are in addition to any margins on the grid cells, so if all the grid items have margin: 2px;
, then the visual distance between grid cells would be at least 1em
plus 4px
.) By default, changes to the gap size causes resizing of the grid items, so that they fill their cells.
This all works because gap
is actually shorthand for the properties row-gap
and column-gap
. The gap: 1em
is interpreted as gap: 1em 1em
, which is shorthand for row-gap: 1em; column-gap: 1em;
. If you want different row and column gap distances, then something like gap: 0.5em 1em
will do nicely.
Gap with Flexbox
Doing the same thing in a flexbox context gives you gaps, but not in quite the same way they happen in grids. Assume the same HTML as above, but this CSS instead:
section {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
The flexboxes are pushed apart by at least the value of gap
here, and (thanks to flex-wrap
) wrap to new flex lines when they run out of space inside their flex container. Changing the gap distance could lead to a change in the wrapping of the flex items, but unlike in Grid, changing gaps between flex items won’t change the sizes of the flex items. Gap changes can cause the flex wrapping to happen at different places, meaning the number of flex items per row will change, but the widths will stay the same (unless you’ve set them to grow or shrink via flex
, that is).
Gap with Multi-Column
In the case of multicolumn content, there is bit of a restriction on gap
: only column gaps are used. You can declare row gaps for multicolumn if you want, but they’ll be ignored.
section {
columns: 2;
gap: 1em;
}
Support
Support for gap
, row-gap
, and column-gap
is surprisingly widespread. Mozilla’s had them since version 61, Chromium since version 66, and thanks to work by Igalia’s Sergio Villar, they’re coming to Safari and Mobile Safari soon (they’re already in the technology preview builds). So if your grid, flex, or multicolumn content needs a bit more space to breathe, get ready to fall into the gap!
Gaps in grid layout will be great, but they don’t fully address the basic problem, which is that CSS provides no good way to manage margin collapsing. What we really need is the
margin-trim
property.I think gap does address this problem, because margins are in a way appropriated to create this gap, but the gap concept goes much further because its being taken into consideration when calculating the available space for items.
Creating gaps with Margins inherently means having to subtract the additional space from the width of a single item, unless you accept the fact that they won’t be exact in flex-contexts where the number of items will exceed the number of columns that exist. Yes, in that case, trimming margin would be nice instead of having to write hard to read
:nth-child(3n+3)
to reset margins on that element.But with gap in flex a lot of code is not needed to be written anymore. That doesn’t mean that
margin-trip
is not a needed property. It just means that I think that usinggap
in layout contexts makes this use here obsolete.I have a hard time using gap in flex-contexts progressively, because I can’t
@support
it.Commendable dissertation, Eric. And very timely, as I am trying to explain to the development team that:
– we can use CSS Grid today
– there are ways to make it work in Internet Exploder
– and sometimes CSS Grid makes more sense than CSS Flexbox
I can’t wait for
gap
to support different gap dimensions for each gap.Something like
row-gap: 1em repeat(5, .5em) 1em;