Sassで色を管理する色々な方法

Sassの便利な機能のひとつに変数があります。変数にマップや@eachを併用すると、柔軟に色を管理することができたり、自動化させることができます。


## 変数
まずはシンプルに変数を使ったパターン。

```scss
$color-twitter: #55acee;
$color-facebook: #3b5998;

.p-button--twitter {
    background-color: $color-twitter;
}

.p-button--facebook {
    background-color: $color-facebook;
}
```

このようにコンパイルされます。

```scss
.p-button--twitter {
  background-color: #55acee;
}

.p-button--facebook {
  background-color: #3b5998;
}
```


## マップ
マップはkeyとvalueのペアを定義できるSassのデータ型のひとつです。

```scss
$map: (
    key1: value1,
    key2: value2,
);
```

[Sassでメディアクエリを効率的に管理するマップとmixin - Qiita](http://qiita.com/manabuyasuda/items/caa823d3644cf3672d05)

`map-get()`関数という指定したkeyのvalueを返す関数と@functionを使って色を管理することができます。

```scss
map-get($map, $key)
```

```scss
$colors: (
    twitter: #55acee,
    facebook: #3b5998,
);

@function colors($key) {
    @return map-get($colors, $key);
}
```

CSSにも`rgba()`などの関数がありますが、Sassの@functionも同じように指定できます。

```scss
.foo {
    color: colors(twitter);
}
```

このようにコンパイルされます。

```css
.foo {
  color: #55acee;
}
```

### マップをネストする

マップはネストして定義することもできます。`map-get()`関数をネストすると、ネストしたマップでもvalueを取得することができます。

```scss
map-get( map-get($map, $key), $nest-key)
```

これを利用すると色のバリエーションを管理をすることができます。

```scss
// ベースになる色を変数で指定しておく。
$color-gray: #888;

// 明るい色と暗い色を`lighten()`関数と`darken()`関数で指定する。
$palettes: (
    gray: (
        base: $color-gray,
        light: lighten($color-gray, 10%),
        dark: darken($color-gray, 10%),
    ),
    black: (
        base: #333,
        light: #666,
        dark: #000,
    ),
);

// `map-get()`関数をネストして値を取得する。
// ネストしたvalueのデフォルトはbaseとする。
@function palettes($key, $tone: base) {
    @return map-get( map-get($palettes, $key), $tone);
}
```

ネストした`base`以外のvalueを取得する場合にだけ第二引数まで指定します。

```scss
.foo {
    color: palettes(gray);
}

.bar {
    color: palettes(black, light);
}
```

このようにコンパイルされます。

```css
.foo {
  color: #888;
}

.bar {
  color: #666;
}
```

## @each
これまでは手動で指定していましたが、@eachを使用することで処理を自動的に繰り返すことができます。

ここでは特定のclassを一括で生成します。マップからkeyとvalueを取得して、それぞれclassとプロパティ値に指定します。`#{$name}`はインターポレーション`#{}`と呼ばれる機能で、変数が指定できない場所でも指定することができるようになります。

```scss
$colors: (
    twitter: #55acee,
    facebook: #3b5998,
);

// @each key, value in $map の順番。
@each $name, $color in $colors {
    .p-button--#{$name} {
        background-color: $color;
    }
}
```

このようにコンパイルされます。

```css
.p-button--twitter {
  background-color: #55acee;
}

.p-button--facebook {
  background-color: #3b5998;
}
```

### リストを併用する

valueをリストにするとフォントと背景色の指定を同時にすることもできます。リストの関数である`nth()`関数を使用して、1つ目と2つ目のvalueをそれぞれ変数に格納します（0からは数えません）。

```scss
$colors: (
    twitter: (#55acee, #fff),
    facebook: (#3b5998, #fff),
);

.p-button {
    @each $name, $color in $colors {
        // valueの1つ目の値を変数に格納する。
        $background-color: nth($color, 1);
        // valueの2つ目の値を変数に格納する。
        $font-color: nth($color, 2);
        &--#{$name} {
            color: $font-color;
            background-color: $background-color;
        }
    }
}
```

このようにコンパイルされます。

```css
.p-button--twitter {
  color: #fff;
  background-color: #55acee;
}
.p-button--facebook {
  color: #fff;
  background-color: #3b5998;
}
```

---

Sassで色を管理する場合、単純にプロパティ値に指定するだけでは変数とマップでそれほど差はないかなと思います（マップの方が読みやすいとは個人的に感じますが）。もしマップを利用するメリットがあるとすれば@eachなどの機能を使って自動化できることだと思います。