SCSSのマップ型変数と繰り返し処理でModifierを一括でつくる

今までカラーを変数化するくらいしかやってませんでしたがマップ型変数と繰り返し処理をすれば一括でModifierを作れることに気づいたので備忘録。

#変数のおさらい
色コードを変数にするだけ:frowning2:

```scss:ただの変数
// ---------------------------------------------------------
// theme color
// ---------------------------------------------------------
$primary: #248888;
$warning: #F0D879;
$danger: #E7475E;

.c-button{
  padding: 0 1em;
  line-height: 24px;
  border-radius: 4px;
  border: 1px solid;
  &--primary{
    background-color: $primary;
  }
  &--warning{
    background-color: $warning;
  }
  &--danger{
    background-color: $danger;
  }
}
```

#マップ型変数
名前（key）、対する値（value）のセットをマップの中に入れる。
`カラー名(primary)`に対する`カラーコード名(#248888)`のセットを、`$theme-colors`というマップのなかに入れる。

```scss:マップ型変数
// ---------------------------------------------------------
// theme color map
// ---------------------------------------------------------
$theme-colors: (
  "primary": #248888,
  "warning": #F0D879,
  "danger": #E7475E,
);
```


```tex
$マップ名: (
  名前1: 値1,
  名前2: 値2
);
```

##変数+マップ型変数
マップ型変数にカラーコード名を直接かかず、先に変数にしてマップ型変数にいれることで、変数は変数として独立して使えるように。

```scss:変数+マップ型変数
// ---------------------------------------------------------
// theme color
// ---------------------------------------------------------
$primary: #248888;
$warning: #F0D879;
$danger: #E7475E;

// ---------------------------------------------------------
// theme color map
// ---------------------------------------------------------
$theme-colors: (
  "primary": $primary,
  "warning": $warning,
  "danger": $danger,
);
```

#繰り返し処理
`@each`で繰り返し処理をする。

```scss:繰り返し処理
// ---------------------------------------------------------
// theme color map
// ---------------------------------------------------------
$theme-colors: (
  "primary": $primary,
  "warning": $warning,
  "danger": $danger,
);

.c-button{
  padding: 0 1em;
  line-height: 24px;
  border-radius: 4px;
  border: 1px solid;
  // 繰り返し処理
  @each $name, $color in $theme-colors {
    &--#{$name} {
      background-color: $color;
    }
  }
}
```
`@each $name, $color in $theme-colors`では
`$theme-colors`の中の、
`key`である`カラー名`を`$name`という変数名に。
`value`である`カラコードの変数`を`$color`という変数名に。

処理内で使う名前をつけてあげてるイメージ。

`$name`はクラス名に使うので`#{}`でかこむ。
`$color`は`background-color`の値に。


そして下記を生成してくれる。

```scss
&--primary{
  background-color: $primary;
}
&--warning{
  background-color: $warning;
}
&--danger{
  background-color: $danger;
}
```

#マップ型変数を入れ子に
例えばサイズ違いのボタンを作るとき、`クラス名`、`width`と`height`を変えたいときなどにつかえる。
２つ以上のプロパティ違いを作成するときに使える。

```scss:マップ型変数を入れ子で使う（map-get関数）
// 変数を作成
// ---------------------------------------------------------
// button size
// ---------------------------------------------------------
$button-large-width: 480px;
$button-large-height: 42px;
$button-small-width: 160px;
$button-small-height: 24px;

// マップ型変数を入れ子で作成
// ---------------------------------------------------------
// button size map
// ---------------------------------------------------------
$button-sizes: (
  "large" :(
    "width": $button-large-width,
    "height": $button-large-height,
  ),
  "small" :(
    "width": $button-small-width,
    "height": $button-small-height,
  )
);
```
`width`または`height`に対する、`サイズ(px)`のセットが
`large`というマップのなかに入っている。
さらに`large`と`small`のマップが`$button-sizes`の中に入ってる。

```tex
$マップ名: (
  $入れ子マップ名1: (
    名前1: 値1,
    名前2: 値2
  ),
  $入れ子マップ名2: (
    名前3: 値3,
    名前4: 値4
  )
);
```

#繰り返し処理でmap-get()関数を使う

```scss
// マップ型変数を入れ子で作成
// ---------------------------------------------------------
// button size map
// ---------------------------------------------------------
$button-sizes: (
 "large" :(
    "width": $button-large-width,
    "height": $button-large-height,
  ),
  "small" :(
    "width": $button-small-width,
    "height": $button-small-height,
  )
);

// @eachで繰り返し処理、map-get関数で入れ子のマップ型変数を使う
.c-button{
  // ~~ その他のプロパティは省略 ~~
  @each $name, $sizes in $button-sizes { //…①
    &--#{$name} {
      height: map-get($sizes, "height");  //…②
      line-height: map-get($sizes, "height");
      width: map-get($sizes, "width");
    }
  }
}
```
下記が生成される

```scss
&--large {
  height: 42px;
  line-height:42px;
  width: 480px;
}
&--small {
  height: 24px;
  line-height:24px;
  width: 160px;
}
```
##①入れ子マップの繰り返し処理
繰り返し処理では`large`が`$name`、
()内の`"width": $button-large-width,"height": $button-large-height,`が`$sizes`となる。

##②map-get関数について

```tex
$マップ名: (
  名前0: 値0,
  $入れ子マップ名1: (
    名前1: 値1,
    名前2: 値2
  )
);
```

上記のようなマップの場合は
`map-get($マップ名, 名前0)`→値0を取得
`map-get($入れ子マップ名1, 名前1)`→値1を取得
になる。


繰り返し処理内の`map-get($sizes, "height")`の場合は`$button-large-height`と`$button-small-height`を取得する。

#CodePen
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="eYeOpKP" data-user="himeka223" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/himeka223/pen/eYeOpKP">
  Untitled</a> by himeka223 (<a href="https://codepen.io/himeka223">@himeka223</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- - -

なんとなく知ってたけど、コーディングに全く使ってなかった…
調べてみたら結構かんたんだった…もっと早く使っときゃよかった。

管理画面とかModifierがめっちゃあるときかなり使えるし、整理されてコードもコンパクトになりそう。
これからガシガシ使っていきたい:relaxed: