一直以来,习惯在 flex 布局中使用 gap
这个属性设置间距,一直以来也都是在最新的 Chrome 上调试,所以从来没有想在 flex gap 在其他浏览器上存在兼容性问题。最近看了一下文档才反应过来,gap
原来只是 grid 布局的属性,虽然近些年来主流浏览器都已经支持了,但是一些使用人数不少的浏览器其实仍然没有支持,包括 UC、QQ,以及运行在 Android 11 上的最新版 MS Edge。
这么方便的属性怎么可能放着它不用呢,于是有人做了 PostCSS 的插件(flex-gap-polyfill),自动对 CSS 里面的 flex box 进行处理,尝试过一下,基本上能用,但是要命的是里面用了很多 css 变量,在 css 代码压缩的时候很容易出问题(有些变量会被 esbuild 判定为无效,直接丢掉了),另外这个插件对处理过 flex box 后,会对 box 里面使用 absolute 定位的元素产生不可预见的影响,总之我并不推荐使用这个插件。
事实上 gap 可以用 margin 很轻易地实现,原理可以看这里,我给它封装了一套 SCSS 的 mixin。
// _polyfills.scss
@use 'sass:math';
@mixin _flex-gap($gap, $row: true) {
$margin: math.div($gap, 2);
$transform: -$margin;
@if $row {
margin-left: $transform;
margin-right: $transform;
} @else {
margin-top: $transform;
margin-bottom: $transform;
}
> * {
@if $row {
margin-left: $margin;
margin-right: $margin;
} @else {
margin-top: $margin;
margin-bottom: $margin;
}
}
}
@mixin flex-gap($gap, $flex-flow: 'row nowrap') {
@if $flex-flow== 'row nowrap' or $flex-flow== 'row-reverse nowrap' {
@include _flex-gap($gap, true);
} @else if $flex-flow== 'column nowrap' or $flex-flow== 'column-reverse nowrap' {
@include _flex-gap($gap, false);
} @else if $flex-flow== 'row wrap' or $flex-flow== 'row-reverse wrap' {
@include _flex-gap($gap, true);
@include _flex-gap($gap, false);
} @else if $flex-flow== 'column wrap' or $flex-flow== 'column-reverse wrap' {
@include _flex-gap($gap, true);
@include _flex-gap($gap, false);
} @else {
@error "The second paramater $flex-flow is set to be '#{$flex-flow}', which is illegal.";
}
}
调用方法:
@use 'polyfills';
.pagination__container {
width: 100%;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: center;
// gap: 6px;
@include polyfills.flex-gap(6px, 'row wrap');
.item__wrapper {
flex: 1 1 auto;
width: 100%;
font-size: 24px;
}
}
注意这套 mixin 借助 margin 来实现,所以建议不用在 flex box 和 flex item 上设置任何 margin,如果需要,在里面或者外面再用一层 wrapper 套起来,在 wrapper 上设置 margin。
另外还有做自适应的需求,在不同屏幕宽度下可能需要设置不同的 flex-flow,可以用下面的 mixin 清除前面的 flex gap:
// _polyfills.scss
@mixin _flex-gap-unset($row: true) {
$margin: 0;
$transform: 0;
@if $row {
margin-left: $transform;
margin-right: $transform;
} @else {
margin-top: $transform;
margin-bottom: $transform;
}
> * {
@if $row {
margin-left: $margin;
margin-right: $margin;
} @else {
margin-top: $margin;
margin-bottom: $margin;
}
}
}
// unset flex-gap, used in @media screen width rules
@mixin flex-gap-unset($flex-flow: 'row nowrap') {
@if $flex-flow== 'row nowrap' or $flex-flow== 'row-reverse nowrap' {
@include _flex-gap-unset(true);
} @else if $flex-flow== 'column nowrap' or $flex-flow== 'column-reverse nowrap' {
@include _flex-gap-unset(false);
} @else if $flex-flow== 'row wrap' or $flex-flow== 'row-reverse wrap' {
@include _flex-gap-unset(true);
@include _flex-gap-unset(false);
} @else if $flex-flow== 'column wrap' or $flex-flow== 'column-reverse wrap' {
@include _flex-gap-unset(true);
@include _flex-gap-unset(false);
} @else {
@error "The second paramater $flex-flow is set to be '#{$flex-flow}', which is illegal.";
}
}
使用:
.flex-box {
position: relative;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
@include polyfills.flex-gap(12px, 'row nowrap');
@media screen and (max-width: 800px) {
flex-flow: column nowrap;
@include polyfills.flex-gap-unset('row nowrap');
@include polyfills.flex-gap(12px, 'column nowrap');
}
}
「樱花庄的白猫」原创文章:《基于 SCSS mixin 的 flex gap polyfill》,转载请保留出处!https://2heng.xin/2021/07/30/flex-gap-polyfill-with-scss-mixins/
Q.E.D.
Comments | 51 条评论
直接把评论区改成display:none可还行
@null 居然被发现了
打卡
打卡![:huaji:](https://jsdelivr.2heng.xin/gh/moezx/cdn@3.1.9/img/Sakura/images/smilies/icon_huaji.gif)