Skip to content

Instantly share code, notes, and snippets.

@frugan-dev
Last active October 25, 2023 21:34
Show Gist options
  • Save frugan-dev/19f94872e4b6005775d91350e87002bf to your computer and use it in GitHub Desktop.
Save frugan-dev/19f94872e4b6005775d91350e87002bf to your computer and use it in GitHub Desktop.
Alternative to flex-gap-polyfill with TWBS 5

In a project with TWBS 5 I tried to use an alternative to flex-gap-polyfill, so I was wondering what advantage I might have in using one solution or the other.
Personally, the alternative I found seems simpler to me, but I would be happy to receive further feedback.

Basically I first added Modernizr which adds the class flexgap or no-flexgap on the html tag:

package.json
"devDependencies": {
    "val-loader": "^5.0.1",
    "val-loader-modernizr": "^1.0.1",
}
.modernizrrc
{
	"minify": true,
	"options": [
		"setClasses"
	],
	"feature-detects": [
		"css/flexgap"
	]
}
webpack.config.js
module: {
  rules: [
    {
      test: /\.modernizrrc$/,
      use: [{
        loader: 'val-loader',
        options: {
          executableFile: require.resolve('val-loader-modernizr'),
        }
      }]
    },
  ]
}

And than I added this SASS code (which can possibly be improved):

main.scss
@use "sass:list";

//https://gist.github.com/frugan-it/19f94872e4b6005775d91350e87002bf
//https://github.com/gavinmcfarland/flex-gap-polyfill/issues/87
//https://stackoverflow.com/a/77140451/3929620
// only Safari < 14.1 (Desktop) and Safari < 14.5 (Mobile) https://caniuse.com/flexbox-gap
.no-flexgap {

  // uncomment to avoid unused values..
  //$spacers-keys: 1, 2, 3, 4;

  @each $breakpoint in map-keys($grid-breakpoints) {
    @include media-breakpoint-up($breakpoint) {
      $infix: breakpoint-infix($breakpoint, $grid-breakpoints);

      //https://github.com/sass/sass/issues/378#issuecomment-1419551287
      $break: 0;
      @each $breakpoint2 in map-keys($grid-breakpoints) {
        @if $break == 0 {
          $infix2: breakpoint-infix($breakpoint2, $grid-breakpoints);

          @each $key, $value in $spacers {
            @if not variable-exists(spacers-keys) or list.index($spacers-keys, $key) {

              .hstack,
              .d#{$infix}-flex {

                &.gap#{$infix2}-#{$key} {
                  //https://stackoverflow.com/a/63796927/3929620
                  margin-bottom: calc(-1 * var(--column-gap-#{$key}, #{$value}));
                  margin-left: calc(-1 * var(--row-gap-#{$key}, #{$value}));

                  > * {
                    margin-bottom: var(--column-gap-#{$key}, #{$value});
                    margin-left: var(--row-gap-#{$key}, #{$value});
                  }
                }
              }
            }
          }

          @if $infix == $infix2 {
            $break: 1;
          }
        }
      }
    }
  }
}

This is the css code obtained:

main.css
.no-flexgap .hstack.gap-1,
.no-flexgap .d-flex.gap-1 {
  margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
  margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
}
.no-flexgap .hstack.gap-1 > *,
.no-flexgap .d-flex.gap-1 > * {
  margin-bottom: var(--column-gap-1, 0.25rem);
  margin-left: var(--row-gap-1, 0.25rem);
}
.no-flexgap .hstack.gap-2,
.no-flexgap .d-flex.gap-2 {
  margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
  margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
}
.no-flexgap .hstack.gap-2 > *,
.no-flexgap .d-flex.gap-2 > * {
  margin-bottom: var(--column-gap-2, 0.5rem);
  margin-left: var(--row-gap-2, 0.5rem);
}
/* and so on... */
@media (min-width: 576px) {
  .no-flexgap .hstack.gap-1,
  .no-flexgap .d-sm-flex.gap-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-1 > *,
  .no-flexgap .d-sm-flex.gap-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-2,
  .no-flexgap .d-sm-flex.gap-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-2 > *,
  .no-flexgap .d-sm-flex.gap-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-sm-1,
  .no-flexgap .d-sm-flex.gap-sm-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-sm-1 > *,
  .no-flexgap .d-sm-flex.gap-sm-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-sm-2,
  .no-flexgap .d-sm-flex.gap-sm-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-sm-2 > *,
  .no-flexgap .d-sm-flex.gap-sm-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
}
@media (min-width: 768px) {
  .no-flexgap .hstack.gap-1,
  .no-flexgap .d-md-flex.gap-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-1 > *,
  .no-flexgap .d-md-flex.gap-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-2,
  .no-flexgap .d-md-flex.gap-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-2 > *,
  .no-flexgap .d-md-flex.gap-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-sm-1,
  .no-flexgap .d-md-flex.gap-sm-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-sm-1 > *,
  .no-flexgap .d-md-flex.gap-sm-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-sm-2,
  .no-flexgap .d-md-flex.gap-sm-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-sm-2 > *,
  .no-flexgap .d-md-flex.gap-sm-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-md-1,
  .no-flexgap .d-md-flex.gap-md-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-md-1 > *,
  .no-flexgap .d-md-flex.gap-md-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-md-2,
  .no-flexgap .d-md-flex.gap-md-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-md-2 > *,
  .no-flexgap .d-md-flex.gap-md-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
}
@media (min-width: 992px) {
  .no-flexgap .hstack.gap-1,
  .no-flexgap .d-lg-flex.gap-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-1 > *,
  .no-flexgap .d-lg-flex.gap-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-2,
  .no-flexgap .d-lg-flex.gap-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-2 > *,
  .no-flexgap .d-lg-flex.gap-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-sm-1,
  .no-flexgap .d-lg-flex.gap-sm-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-sm-1 > *,
  .no-flexgap .d-lg-flex.gap-sm-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-sm-2,
  .no-flexgap .d-lg-flex.gap-sm-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-sm-2 > *,
  .no-flexgap .d-lg-flex.gap-sm-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-md-1,
  .no-flexgap .d-lg-flex.gap-md-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-md-1 > *,
  .no-flexgap .d-lg-flex.gap-md-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-md-2,
  .no-flexgap .d-lg-flex.gap-md-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-md-2 > *,
  .no-flexgap .d-lg-flex.gap-md-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-lg-1,
  .no-flexgap .d-lg-flex.gap-lg-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-lg-1 > *,
  .no-flexgap .d-lg-flex.gap-lg-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-lg-2,
  .no-flexgap .d-lg-flex.gap-lg-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-lg-2 > *,
  .no-flexgap .d-lg-flex.gap-lg-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
}
@media (min-width: 1200px) {
  .no-flexgap .hstack.gap-1,
  .no-flexgap .d-xl-flex.gap-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-1 > *,
  .no-flexgap .d-xl-flex.gap-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-2,
  .no-flexgap .d-xl-flex.gap-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-2 > *,
  .no-flexgap .d-xl-flex.gap-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-sm-1,
  .no-flexgap .d-xl-flex.gap-sm-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-sm-1 > *,
  .no-flexgap .d-xl-flex.gap-sm-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-sm-2,
  .no-flexgap .d-xl-flex.gap-sm-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-sm-2 > *,
  .no-flexgap .d-xl-flex.gap-sm-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-md-1,
  .no-flexgap .d-xl-flex.gap-md-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-md-1 > *,
  .no-flexgap .d-xl-flex.gap-md-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-md-2,
  .no-flexgap .d-xl-flex.gap-md-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-md-2 > *,
  .no-flexgap .d-xl-flex.gap-md-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-lg-1,
  .no-flexgap .d-xl-flex.gap-lg-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-lg-1 > *,
  .no-flexgap .d-xl-flex.gap-lg-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-lg-2,
  .no-flexgap .d-xl-flex.gap-lg-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-lg-2 > *,
  .no-flexgap .d-xl-flex.gap-lg-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-xl-1,
  .no-flexgap .d-xl-flex.gap-xl-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-xl-1 > *,
  .no-flexgap .d-xl-flex.gap-xl-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-xl-2,
  .no-flexgap .d-xl-flex.gap-xl-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-xl-2 > *,
  .no-flexgap .d-xl-flex.gap-xl-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
}
@media (min-width: 1400px) {
  .no-flexgap .hstack.gap-1,
  .no-flexgap .d-xxl-flex.gap-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-1 > *,
  .no-flexgap .d-xxl-flex.gap-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-2,
  .no-flexgap .d-xxl-flex.gap-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-2 > *,
  .no-flexgap .d-xxl-flex.gap-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-sm-1,
  .no-flexgap .d-xxl-flex.gap-sm-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-sm-1 > *,
  .no-flexgap .d-xxl-flex.gap-sm-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-sm-2,
  .no-flexgap .d-xxl-flex.gap-sm-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-sm-2 > *,
  .no-flexgap .d-xxl-flex.gap-sm-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-md-1,
  .no-flexgap .d-xxl-flex.gap-md-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-md-1 > *,
  .no-flexgap .d-xxl-flex.gap-md-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-md-2,
  .no-flexgap .d-xxl-flex.gap-md-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-md-2 > *,
  .no-flexgap .d-xxl-flex.gap-md-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-lg-1,
  .no-flexgap .d-xxl-flex.gap-lg-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-lg-1 > *,
  .no-flexgap .d-xxl-flex.gap-lg-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-lg-2,
  .no-flexgap .d-xxl-flex.gap-lg-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-lg-2 > *,
  .no-flexgap .d-xxl-flex.gap-lg-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-xl-1,
  .no-flexgap .d-xxl-flex.gap-xl-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-xl-1 > *,
  .no-flexgap .d-xxl-flex.gap-xl-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-xl-2,
  .no-flexgap .d-xxl-flex.gap-xl-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-xl-2 > *,
  .no-flexgap .d-xxl-flex.gap-xl-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
  .no-flexgap .hstack.gap-xxl-1,
  .no-flexgap .d-xxl-flex.gap-xxl-1 {
    margin-bottom: calc(-1 * var(--column-gap-1, 0.25rem));
    margin-left: calc(-1 * var(--row-gap-1, 0.25rem));
  }
  .no-flexgap .hstack.gap-xxl-1 > *,
  .no-flexgap .d-xxl-flex.gap-xxl-1 > * {
    margin-bottom: var(--column-gap-1, 0.25rem);
    margin-left: var(--row-gap-1, 0.25rem);
  }
  .no-flexgap .hstack.gap-xxl-2,
  .no-flexgap .d-xxl-flex.gap-xxl-2 {
    margin-bottom: calc(-1 * var(--column-gap-2, 0.5rem));
    margin-left: calc(-1 * var(--row-gap-2, 0.5rem));
  }
  .no-flexgap .hstack.gap-xxl-2 > *,
  .no-flexgap .d-xxl-flex.gap-xxl-2 > * {
    margin-bottom: var(--column-gap-2, 0.5rem);
    margin-left: var(--row-gap-2, 0.5rem);
  }
  /* and so on... */
}

which may possibly be limited to only some values by appropriately uncommenting and valorising the variable $spacers-keys.

@gavinmcfarland
Copy link

gavinmcfarland commented Oct 21, 2023

In principle, this is a good solution. It's much easier to debug with and understand. So long as flex layout properties are always used with a class-based system, as in, flex properties are contained to their own classes such as in your example hstack and gap-*, then this should be relatively easy to manage.

Two main drawbacks to this method are:

  • You'll need to remember to account for the negative margin, when apply a margin to a container that uses this technique
  • It won't work if you have nested containers with flex layout applied

Some things I'd check:

  • When you have a container that is full width of the viewport, you might find that margin-right causes a scrollbar to appear. Using margin-left avoids this.
  • Check that things are still clickable when a negative margin container is next to a button. There is a CSS property you can use to workaround this, but I forget what it's called.

Something to consider:

You can use flex-gap-polyfill in a slimmed-down version by restricting the polyfill to only apply to specific class names.

For example:

{
    only: [".hstack", /gap-.+/]
}

It's been a while since I configured it with a regex, but something like that would work.

@frugan-dev
Copy link
Author

Hi @gavinmcfarland, thank you for your attention and detailed response, I'm very pleased with your opinion!

Indeed my solution is limited only to TWBS 5, as well as having the drawbacks you mention..

When you have a container that is full width of the viewport, you might find that margin-right causes a scrollbar to appear. Using margin-left avoids this.

I modified the code using margin-left as per your advice, thanks!

Check that things are still clickable when a negative margin container is next to a button. There is a CSS property you can use to workaround this, but I forget what it's called.

I searched online, but couldn't find anything about it... I also looked here https://www.w3schools.com/cssref/index.php.

You can use flex-gap-polyfill in a slimmed-down version by restricting the polyfill to only apply to specific class names.

Thanks, I missed this possibility.. I'll try it! 😉

@gavinmcfarland
Copy link

I remembered the property.

It's pointer-events: none.

In my polyfill I add it to the container and then re-enable it on the children elements using a wildcard.

.container {
  pointer-events: none;
}

.container > * {
  pointer-events: auto;
}

@frugan-dev
Copy link
Author

@gavinmcfarland Thank you very much for the tip!
For now I don't encounter this problem.. perhaps with TWBS setup this problem doesn't occur?!
Anyway good to know in case it comes up!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment