Sass(Scss) Memo: 変数

今回は変数についてです。
$ から始めて、値はCSSと同じようにして設定します。
こんな感じ。

Scss
$margin: 2em 0;  // $margin に "2em 0" をいれて定義する。
h1 {
    margin: $margin;
}
CSS
h1 {
  margin: 2em 0;
}

変数はそれが記述された{}内でのみ有効になります。
どのCSSルールセットやmixinにも含まれない場合、どこでも使えるグローバルな変数になります。
こんな感じ。

Scss
h1 {
    $margin: 2em 0;  // ここで$marginを定義する。
    margin: $margin;
}
p {
    margin: $margin; // ここでは使えない!コンパイル時にエラーになります。
}

インターポレーション

変数はプロパティの値だけでなく、セレクター名やプロパティ名にも使うことができます。
その場合、#{}を使うインターポレーションと呼ばれる書き方をします。
こんな感じ。

Scss
$class: title;
$property: top;
h1.#{$class} {
    margin-#{$property}: 2em 0;
}
CSS
h1.title {
  margin-top: 2em 0;
}

インターポレーションを使った場合、変数内の引用符は自動的に削除されます。
mixinの引数をセレクターに利用するなんて時にやりやすくするためらしいです。
.(ドット)から始まる文字列はmixinの引数にはできないので引用符で囲んであげる必要があるわけです。
こんな感じ。

Scss
@mixin color-red($selector) {
    #{$selector} {
        color: red;
    }
}
@include color-red(".title");  // 引用符で囲む。
CSS
.title {  /* 引用符が削除されました。 */
  color: red;
}

インターポレーションを使うとその近くの算術演算(+, -, *, /など)は通常のテキストとして扱われます。
こんな感じ。

Scss
$font-size: 24px;
$line-height: 1.2;
h1 {
    font: $font-size/$line-height;  // ふつうに記述。
    font: #{$font-size}/#{$line-height};  // インターポレーションをつかう。
}

$img-path: "/shared/img";
.header {
    background-image: url(#{$img-path}/bg_header.png);  // 画像のパスに使うときにも。
}

$var1: foo;
$var2: bar;
.test {
    content: $var1 + $var2;
    content: #{$var1} + #{$var2};

    content: $var1 - $var2;
    content: #{$var1} - #{$var2};
}
CSS
h1 {
  font: 20px;  /* 計算されてしまいました。 */
  font: 24px/1.2;
}

.header {
  background-image: url(/shared/img/bg_header.png);
}

.test {
  content: foobar;     /* +とスペースがなくなり連結された。 */
  content: foo + bar;  /* +とスペースはそのまま。 */
  content: foo-bar;    /* -はそのままで、スペースがなくなった。 */
  content: foo - bar;  /* -とスペースはそのまま。 */
}

計算や結合させたければ普通に記述して、そうでない場合はインターポレーションで記述すれば大丈夫ですね。

変数のデフォルト値

変数には !default で初期値を設定することができます。
変数にすでに値が代入されている場合、その値を上書きしません。値がすでに代入されていない場合は通常通り指定された値を代入します。
こんな感じ。

Scss
$var1: foo;
$var1: bar !default;
.test {
    content: $var1;  // 通常なら後で代入した bar が出力されるが、、
}

$var2: bar !default;
.test {
    content: $var2;  // 先に値が代入されていなければ、、
}
CSS
.test {
  content: foo;  /* foo が出力されました。 */
}

.test {
  content: bar;  /* bar が出力されました。 */
}

!default はCSSでいう !important の逆みたいなもんですかね。