使用scss+mixin整理你的媒体查询代码

896 阅读4分钟

本文由团队成员 BingLee1994 撰写,已授权涂鸦大前端独家使用,包括但不限于编辑、标注原创等权益。

前言

做后台页面的同学一定体会不到做前台页面的痛苦,尤其是像官网类,产品介绍这种门面网站,她代表着公司的素质和实力,因为用户了解一个公司总是先打开一个公司的官网,因此官网页面不允许出现丝毫bug,哪怕是像素级别的。

所以官网页面的代码中css可能较多,甚至可能多于js,那么再加上pc, pad, mobile三端的响应式css代码,就会导致后期维护成本增加,很有可能不知怎么的页面某个css属性突然被覆盖了,导致页面跨掉了,因为如果不好好维护,那么海量的css代码特别容易藏污纳垢,是滋生bug的好地方。

今天分享一个很久以前自己写的小工具帮助你整理媒体查询代码。

示范

我这个代码的思路是:在一个css选择器里一次性写全她所有的三端的媒体查询代码,当然也有人喜欢:在一个媒体查询里写全所有css选择器属于当前媒体的代码,这两个哪个好哪个坏没法比较,适合自己的才是最好的。

实际使用起来就像下面这样,写四行,第一行是属性名,剩下三行每行代表一个设备的媒体查询代码

.cardList {
  display: flex;
  align-items: stretch;

  @include responsiveProps(
    (margin, flex-wrap, color),
    (32px 0, nowrap,    #121314), //用于pc
    (24px 0, nowrap,    #4D85FF), //用于pad
    (20px 0, wrap,      #4D85FF), //用于mobile
  )
}

编译完之后会像下面这样:


.cardList {
  display: flex;
  align-items: stretch;
}
@media screen and (min-width: 1024px) {
  .cardList {
    margin: 32px 0;
    flex-wrap: nowrap;
    color: #121314;
  }
}
@media screen and (min-width: 768px) and (max-width: 1023px) {
  .cardList {
    margin: 24px 0;
    flex-wrap: nowrap;
    color: #4D85FF;
  }
}
@media screen and (max-width: 767px) {
  .cardList {
    margin: 20px 0;
    flex-wrap: wrap;
    color: #4D85FF;
  }
}

这样借助scss mixin可以自动帮我把代码整理到对应的媒体查询里,不仅仅省去了大量代码,而我们只需要在一处进行管理即可,不用在海量代码里四处搜寻,越少的代码意味着更好的维护。

可以搭配原生css变量吗?

必须可以,就像下面这样:

.cardList {
  --accent-color: #121314;
  --my-grid-col-size: 1;
  --my-grid-gutter: 24px;
  --single-row-height: 128px;

  display: grid;
  grid-template-columns: repeat(var(--my-grid-col-size), auto);
  grid-auto-rows: var(--single-row-height);
  gap: var(--my-grid-gutter);
  color: var(--accent-color);

  @include responsiveProps(
    (--accent-color,  --my-grid-col-size,  --my-grid-gutter, --single-row-height),
    (#121314,           4,                 24px,              128px), //用于pc
    (#4D85FF,           2,                 24px,              200px), //用于pad
    (#4D85FF,           1,                 20px,              240px), //用于mobile
  )
}

最终编译出来如下:

.cardList {
  --accent-color: #121314;
  --my-grid-col-size: 1;
  --my-grid-gutter: 24px;
  --single-row-height: 128px;
  display: grid;
  grid-template-columns: repeat(var(--my-grid-col-size), auto);
  grid-auto-rows: var(--single-row-height);
  gap: var(--my-grid-gutter);
  color: var(--accent-color);
}
@media screen and (min-width: 1024px) {
  .cardList {
    --accent-color: #121314;
    --my-grid-col-size: 4;
    --my-grid-gutter: 24px;
    --single-row-height: 128px;
  }
}
@media screen and (min-width: 768px) and (max-width: 1023px) {
  .cardList {
    --accent-color: #4D85FF;
    --my-grid-col-size: 2;
    --my-grid-gutter: 24px;
    --single-row-height: 200px;
  }
}
@media screen and (max-width: 767px) {
  .cardList {
    --accent-color: #4D85FF;
    --my-grid-col-size: 1;
    --my-grid-gutter: 20px;
    --single-row-height: 240px;
  }
}

原生css变量节省css代码,而且让css代码可读性大大增强,强烈推荐使用(如果不兼容IE11)。

设计思路

这里借助了mixin的数组特性,将媒体查询代码以数组形式传入,通过循环和下标取出不同设备的css值,然后放在媒体查询里。

有一点需要注意,同级选择器,靠后的代码优先级高

整个工具思路比较简单,就不赘述了,直接贴代码,这里没有做非空判断,感兴趣的同学可以再重构下,希望能够助你开发:

$mobile-size: 768px;
$pad-size: 1024px;
$pc-size: 1025px;
$max-size: 1440px;

@mixin forMobile {
  @media screen and (max-width: ($mobile-size - 1px)) {
    @content;
  }
}

@mixin forPad {
  @media screen and (min-width: $mobile-size) and (max-width: ($pad-size - 1)) {
    @content;
  }
}

@mixin forPC {
  @media screen and (min-width: $pad-size) {
    @content;
  }
}

@mixin forWidenPC {
  @media screen and (min-width: $max-size) {
    @content;
  }
}

@mixin responsiveProp($propName, $valPC, $valPad, $valMobile) {
  @include forPC {
    #{$propName}: $valPC;
  }

  @include forPad {
    #{$propName}: $valPad;
  }

  @include forMobile() {
    #{$propName}: $valMobile;
  }
}

@mixin responsiveProps($propNames, $valsPC, $valsPad, $valsMobile) {
  @include forPC {
    @for $i from 1 through length($propNames) {
      $propName: nth($propNames, $i);
      $valPC: nth($valsPC, $i);

      #{$propName}: $valPC;
    }
  }

  @include forPad {
    @for $i from 1 through length($propNames) {
      $propName: nth($propNames, $i);
      $valPad: nth($valsPad, $i);

      #{$propName}: $valPad;
    }
  }

  @include forMobile() {
    @for $i from 1 through length($propNames) {
      $propName: nth($propNames, $i);
      $valMobile: nth($valsMobile, $i);

      #{$propName}: $valMobile;
    }
  }
}

如果你有更多使用css技巧,欢迎随时讨论!