A grid-gap-like solution for Flexbox
Sometimes, working with CSS can be frustrating (to be fair, I mostly work with SASS and haven’t touched vanilla CSS in ages). That said, CSS has come a long way in recent years — with amazing features like Custom Properties, Grid, and Flexbox.
What I particularly love about CSS Grid is the gap
property. It lets you create space between items — without affecting the space around the container itself.
Sounds great, right? Let’s just use that everywhere!
Well… not so fast. At the time of writing this, Flexbox didn’t support the gap
property. Hopefully it’ll stick around now that it’s finally supported. (If you know why it took so long — or if it’s still buggy somewhere — feel free to share!) If you wanted gap
-like spacing in Flexbox back then, you had to rely on the classic “margin
on first/last child” workaround. SASS gives us powerful tools like mixins, functions, loops, and more — all things we still don’t have in plain CSS. (Also: I’ll never stop loving the clean, structured look of SASS. 💘)
Enough talk — let’s look at some code so you can see how this workaround works in practice.
scss
=flexGap( $gap, $direction: row, $element: div )
> #{$element}
@if $direction == row
margin: 0 $gap/2
&:first-child
margin-left: 0
&:last-child
margin-right: 0
@if $direction == column
margin: $gap/2 0
&:first-child
margin-top: 0
&:last-child
margin-bottom: 0;
.container
display: flex
+flexGap( 20px );
Okay, lets have a look at what I’ve done — what the mixin does is, to select each of the containers children (so you could use the mixin on a Flexbox-Container it self, just like the grid-gap property, not on its children, as you would do it by using margin), adds some margin to them, and removes the first- and last-child margin (left and right).
If you add a direction to the mixin (for example column, if your Flexbox-Containers flex-direction is setted to column, this would make sense), you could remove the children margin-top (first-child) or margin-bottom (last-child) — so the Mixin works with “flex-direction: column” as well.
scss
.container
display: flex
flex-direction: column
+flexGap( 20px, column );
By default the mixin will effect all divs, which are children of the container. If you flex-container items are of another element-type you could use the Mixins $element statement to set the related element-type or a class or an id as a selector.
scss
.container
display: flex
flex-direction: column
+flexGap( 20px, column, span);
.container
display: flex
flex-direction: column
+flexGap( 20px, column, ".myClass");
By setting classes or id’s to the flex-container-items you could also just give these different gaps, as well.
scss
.container
display: flex
+flexGap( 10px, row, ".aClass")
+flexGap( 20px, row, ".anotherClass")
+flexGap( 30px, row, ".oneMoreClass");
By calling the mixin several times you wont overwrite the first call, instead SASS will generate several instances of the CSS result — so compiled SASS code above would look like the following in CSS:
scss
.test > .aClass {
margin: 0 5px; }
.test > .aClass:first-child {
margin-left: 0; }
.test > .aClass:last-child {
margin-right: 0; };
.test > .anotherClass {
margin: 0 10px; }
.test > .anotherClass:first-child {
margin-left: 0; }
.test > .anotherClass:last-child {
margin-right: 0; };
.test > .oneMoreClass {
margin: 0 15px; }
.test > .oneMoreClass:first-child {
margin-left: 0; }
.test > .oneMoreClass:last-child {
margin-right: 0; };
The gap within the flexGap-Mixin can be setted up as a static value (pixel, rem) or a dynamic value (percent, view-port-width), as well — also there is one little, kind of cool side effect! By changing the direction (from flex-row to flex-columns or vice versa) the container-items will have a little transition, if one sets a transition to it — of course this is optional by setting a transition.