Sassでの色管理

Sassでは色を変数として定義でき、また様々な関数でそれを操作することが可能になっている。そのため色を論理的に管理することが可能になっているが、これといった手法が確立されているわけではない。このウェブサイトでは少しややこしい形で管理するようにしている。どういう目的でこういう複雑な構造になっているのかを簡単に書いておきたい。

基本色の定義

基本色、つまりテーマカラーであったり、本文の背景色や文字色といった見た目のイメージを決定する色は、色コードを直接指定して定義する必要がある。これはほぼ間違いなくみんな同じように書いているだろう。

$color-dark: rgb(60, 51, 48);
$color-light: rgb(252, 249, 240);
$color-accent: rgb(17, 136, 187);

これらは背景色であったり文字色、そしてリンクの文字色として使っているが、まずはその色がどのようなタイプの色かを直接表した変数名で定義している。ここで変数名の実際に利用されるコンテキストにおけるセマンティクスを重視しないのは、色を大きく変更した時にそのまま機能しないからだ。

これらの色は後々混ぜたり、明るくしたり、暗くしたり、と様々な変形を加える事になるわけだが、そういった変形はその色(特に明度)に依存することが多い。例えば以下のように基本色とその変形を定義したとしよう。

$color-bg: rgb(238, 238, 238);
$color-bg_quote: darken($color-bg, 10%);

引用ブロックの背景色を少し暗くするというものだ。この時点ではもちろん機能するが、仮に$color-bgをもっと暗い色にした場合、引用ブロックの背景色は意図したような違いを得ることはできなくなるだろう。元々を明るい色や暗い色と定義しておくと、このような問題は起きにくい。

基本色のバリエーション

見た目の統一感を出すために、基本色の濃淡を変化させた色や、補色といった論理的な関係をもつ色をうまく使っていきたい。例えばボールドで表示される見出しが強くなりすぎないように本文の文字色より少し薄くするなどだ。このようなバリエーションをあらかじめ作っておくと、色の変更を局所に止めることが出来る。

例えば先程の引用ブロックの背景色の例を考えてみよう。

$color-light: rgb(238, 238, 238);
$color-bg_quote: darken($color-light, 10%);

単純に基本色を使うとこうなるだろう。$color-lightの調節に連動して引用ブロックの背景色も変化する。しかしこれでは再利用性に欠ける。この10%暗くした色を引用ブロック以外でも使うことはあるだろうが、その変数名を考えると使いづらいものになる。あらかじめバリエーションを定義しておき、それを参照するような形にすると再利用性が向上する。

$color-light: rgb(238, 238, 238);
$color-tint--light: darken($color-light, 10%);

blockquote {
  background-color: $color-tint--light;
}

.foo {
  background-color: $color-tint--light;
}

別の方向から見るとblockquote.fooの色を扱うプロパティーで、基本色を変形させる関数などを直接使わないようにするということだ。こうすることによって関数を読み解くことなく色を把握することが可能になり、その色は全体の見た目の中でどのような振る舞いをする色なのかを表現することが出来る。後者の色の振る舞いに関しては、上記例のようにBEMを流用した強力な命名規則も合わせて必要になってくる。

変数名のセマンティクス

基本色とそのバリエーションはセマンティクス(CSSを適用する文書におけるそれ)を無視した形で定義してきた。それらの変数の参照は簡単なものだが、Sassではウィジェットごとに分割して開発を行うことが多いので、色の管理が散らばってしまうことにもなる。色の管理を単独のファイルに集約させるためにはセマンティクスを重視した変数名を更に作ってやる必要があるだろう。

$color-light: rgb(238, 238, 238);
$color-accent: rgb(17, 136, 187);

$color-tint--light: darken($color-light, 10%);

$color-fg_link: $color-accent;
$color-fg_link--hover: $color-light;
$color-bg_link--hover: $color-accent;
$color-bg_blockquote: $color-tint--light;
$color-bg_foo: $color-tint--light;

以降で基本色とそのバリエーションを使うことがないように、利用される要素やクラス名を流用した変数名で再定義するという形になる。ここではBEMを使って定義したが、明確なルールがあるならなんでも良い。

a {
  color: $color-fg_link;

  &:hover {
    color: $color-fg_link--hover;
    background-color: $color-bg_link--hover;
  }
}

blockquote {
  background-color: $color-bg_blockquote;
}

.foo {
  background-color: $color-bg_foo;
}

実際にはこれらのルールはそれぞれのSCSSファイルで書かれることになるが、このように明確な命名規則に基づいた変数を参照するように書くだけで良い。明確なルール付けに基づいた変数名なので、これらのルールセットを書く時には色の定義はおろかその存在や実際にどのような色なのかを考える必要はまったくない。ルールセットが完成したら改めて色定義を行っているSCSSファイルに色定義を追加する、というように色の管理を一元化することが可能になるわけだ。


基本色とそのバリエーションの定義まではこれからも成立すると思うが、Web Componentsという未来がちらついている今は、一元化よりもコンポーネント単位での定義の方が未来がありそうな気がしている。Sass 3.3まではグローバル変数での管理を強いられていたので、一元化の方がメリットが大きかった。しかしSass 3.4でローカル変数の扱いが変わり、グローバル変数に縛られなくなるので、徐々にコンポーネントを意識した管理へ変えていこうと考えている。

当面はSass 3.4を前提として書くことはできないので、3.3との兼ね合いも考慮する必要がある。そうなると管理の一元化を捨て、セマンティクスを重視した変数名を各SCSSファイルで定義するというような、最終的にローカル変数での定義へ移行することを見据えた形に落ち着くことになるだろう。