藉助sass的Maps功能使得響應式代碼更有條理

原文來自這裏
本文綜合了原文(by Jonathan Suh)以及筆者本身的理解。html

Introduction

衆所周知,寫代碼與寫維護性高的代碼是兩回事.而涉及到響應式,代碼又特別容易變的雜亂.藉助sass maps所提供的拓撲功能,咱們能夠嘗試減輕這一痛點.
如下的代碼仍是很常見的:git

p { font-size: 15px; }

@media screen and (min-width: 480px) {
  p { font-size: 16px; }
}
@media screen and (min-width: 640px) {
  p { font-size: 17px; }
}
@media screen and (min-width: 1024px) {
  p { font-size: 19px; }
}

兩個問題點:1.DRY, 2.Magic Number.
也許sass的變量能夠解決問題2。github

$p-font-size-mobile : 15px;
$p-font-size-small  : 16px;
$p-font-size-medium : 17px;
$p-font-size-large  : 19px;

可是變量多了以後,代碼會變成這樣:sass

$p-font-size-mobile : 15px;
$p-font-size-small  : 16px;
$p-font-size-medium : 17px;
$p-font-size-large  : 19px;

$h1-font-size-mobile: 28px;
$h1-font-size-small : 31px;
$h1-font-size-medium: 33px;
$h1-font-size-large : 36px;

..............

超多的變量顯得毫無章法。工具

Sass maps初試

聲明以下的sass變量:佈局

$p-font-sizes: (
  null  : 15px,
  480px : 16px,
  640px : 17px,
  1024px: 19px
);

接下來,建立mixin,遍歷屬性,生成對應的media queries.net

@mixin font-size($fs-map) {
  @each $fs-breakpoint, $fs-font-size in $fs-map {
    @if $fs-breakpoint == null {
      font-size: $fs-font-size;
    }
    @else {
      @media screen and (min-width: $fs-breakpoint) {
        font-size: $fs-font-size;
      }
    }
  }
}

Sass 還提供了一些其它的語法糖,能夠參考這裏code

這時咱們能夠在任意的地方引入mixinhtm

p {
  @include font-size($p-font-sizes);
}

結果和文章開頭是同樣的.get

Solving Breakpoint Fragmentation

上面的代碼彷佛仍是有一點脆弱,若是咱們但願引入更多的Breakpoint,或着說p tag 與h1 tag 但願引入不一樣的Breakpoint.事情就會變的很麻煩.考慮到這一點,咱們能夠將代碼進行重構.

$breakpoints: (
  small : 480px,
  medium: 700px, // Previously 640px
  large : 1024px
);

$p-font-sizes: (
  null  : 15px,
  small : 16px,
  medium: 17px,
  large : 19px
);

$h1-font-sizes: (
  null  : 28px,
  small : 31px,
  medium: 33px,
  large : 36px
);

@mixin font-size($fs-map, $fs-breakpoints: $breakpoints) {
  @each $fs-breakpoint, $fs-font-size in $fs-map {
    @if $fs-breakpoint == null {
      font-size: $fs-font-size;
    }
    @else {
      // If $fs-font-size is a key that exists in
      // $fs-breakpoints, use the value
      @if map-has-key($fs-breakpoints, $fs-breakpoint) {
        $fs-breakpoint: map-get($fs-breakpoints, $fs-breakpoint);
      }
      @media screen and (min-width: $fs-breakpoint) {
        font-size: $fs-font-size;
      }
    }
  }
}

如今,咱們能夠隨意的添加Breakpoint

$p-font-sizes: (
  null  : 15px,
  small : 16px,
  medium: 17px,
  900px : 18px,
  large : 19px,
  1440px: 20px,
);

p {
  @include font-size($p-font-sizes);
}

Improving Vertical Rhythm With Line Height

來,更進一步,咱們能夠font-size mixin中增長一個lineheight的配置,(line-height和font-size經常是同時出現的)

$breakpoints: (
  small : 480px,
  medium: 700px,
  large : 1024px
);

$p-font-sizes: (
  null  : (15px, 1.3),
  small : 16px,
  medium: (17px, 1.4),
  900px : 18px,
  large : (19px, 1.45),
  1440px: 20px,
);

@mixin font-size($fs-map, $fs-breakpoints: $breakpoints) {
  @each $fs-breakpoint, $fs-font-size in $fs-map {
    @if $fs-breakpoint == null {
      @include make-font-size($fs-font-size);
    }
    @else {
      // If $fs-font-size is a key that exists in
      // $fs-breakpoints, use the value
      @if map-has-key($fs-breakpoints, $fs-breakpoint) {
        $fs-breakpoint: map-get($fs-breakpoints, $fs-breakpoint);
      }
      @media screen and (min-width: $fs-breakpoint) {
        @include make-font-size($fs-font-size);
      }
    }
  }
}

// Utility function for mixin font-size
@mixin make-font-size($fs-font-size) {
  // If $fs-font-size is a list, include
  // both font-size and line-height
  @if type-of($fs-font-size) == "list" {
    font-size: nth($fs-font-size, 1);
    @if (length($fs-font-size) > 1) {
      line-height: nth($fs-font-size, 2);
    }
  }
  @else {
    font-size: $fs-font-size;
  }
}

nth 是sass提供的語法,nth(list, n)從list中拿第n個數據.

Conclusion

上文所提供的代碼仍是有不少不健壯的地方,歡迎你們提意見,共同研究.

RESOURCES

一個響應式佈局分析能夠用到的工具Modular Scale
另一篇很棒的博文

若是以爲文章不錯,歡迎來個人github看看,右上角圖標即爲傳送門。

相關文章
相關標籤/搜索