experimental Flex-Gap mixin

  • CSS

    Sass Mixins

An experimental Flex-Gap property using a custom Sass mixin

Sometimes, working with CSS can be frustrating (to be fair, I mostly work with SASS and haven’t touched vanilla CSS in ages). This article is deprecated – back when I wrote it, the gap property wasn’t supported in Flexbox. Now it is. Still, this post might contain some useful insights, so I’ll leave it online. Why didn’t Flexbox support gap like grid gap) for so long? (Meanwhile, yes, gap does work with Flexbox now.) This article explores an experimental workaround using SASS mixins to replicate gap behavior in Flex layouts — before native support was available.

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

// a mixin to add grid-gap to flexbox
=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;

// easy to use by just adding it to the flex-container
.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

// also supporting flex-directions
.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

// If you just want to select an element you could write it plane into the mixin.
.container
  display: flex
  flex-direction: column
  +flexGap( 20px, column, span);
	
// If you want to select a class or an id you'd have to put the selector into quote marks.
.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

// different gaps for different classes
.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

// This is what the compiled SASS would look like within you CSS-File

.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.

See some examples

Here is some demonstration/example of how to use this — just play around, fork, comment, like — do what ever you want with this pen.

html

<iframe class="w-full" width="800" height="800" scrolling="no" title="A Flex-Gap Mixin (experimental)" src="https://codepen.io/lazercaveman/embed/preview/bGbMZgd?default-tab=result&editable=true&theme-id=dark" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">See the Pen <a href="https://codepen.io/lazercaveman/pen/bGbMZgd">A Flex-Gap Mixin (experimental)</a> by Ali Soueidan (<a href="https://codepen.io/lazercaveman">@lazercaveman</a>)on <a href="https://codepen.io">CodePen</a>.</iframe>

The flexGap-Mixin is very small, easy to use and it adds some additional functionality to Flex-Box — if you would add some functionality or change any of its attribute just let me know how and why— if you’d like to use it just go for it – it’s also available on GitHub .