CSS、Sassでの変数の書き方

Hugoブログを絶賛カスタム中です。
(テーマは「Clarity」を使っています)

このテーマではSassが使われているのですが、変数を用いて色やwidthの数値を設定しています。

そしてなぜかSassの中でcssのカスタムプロパティを使っていました。
しかも私にとって馴染みの薄いSASS記法...。

Sass(SCSS記法)でSassの変数を使うことはあっても、このテーマのような使い方はしたことがありませんでした。

今までカラーコードの統一ぐらいにしか利用できていないので、この機会に調べてまとめます。

CSSの変数・カスタムプロパティ

cssで変数の定義、呼び出し、ということができます。

参考記事です。

CSSで変数(カスタムプロパティ)を使ってみよう | Webクリエイターボックス

CSSの変数(カスタムプロパティ)便利な使い方を詳しく解説 | コリス

変数の定義

:root {
  --var_name: value;
}

--変数名: カラーコードや単位付きの数値など;

です。

値には''などクォーテーションは必要ありません。
また --sukima: margin などのように、プロパティ名は設定できません。

この場合は :root 以下の子要素で var_name という変数を呼び出すことができる設定になります。

要素に対してプロパティに当たる変数を設定するので「カスタムプロパティ」というのでしょうね。

この↑後に同じ変数に別の値を再定義することができます。

再定義は、子要素に対して、と
同要素に対してウィンドウサイズのメディアクエリなどで、行います。

※「再定義」と書いてますが、これはこのままこのような考え方でいいのか、それともスコープが異なるとはいえ同名の変数に値を入れるので「代入」として考えた方がいいのか、分からなくなってしまいました。

他の言語でもスコープの概念は出てきますし基礎的な部分だと思うので、判明したら修正しようと思います!

:root {
  --font-large: 20px;
  --font-small: 16px;
}

/* 子要素で再代入 */
.child {
  --font-large: 16px;
  --font-small: 14px;
}

/* メディアクエリで再代入 */
@media screen and (min-width: 769px) {
  :root {
    --font-large: 18px;
    --font-small: 12px;
  }
}

実はメディアクエリでの変数の定義・再定義は、CSS変数のみSass変数ではできません。

:root とは

:root - CSS: カスケーディングスタイルシート | MDN

CSS の :root 疑似クラスは、文書を表すツリーのルート要素を選択します。 HTML では、 :root は 要素を表し、詳細度が高いことを除けば html セレクターと同等です。

:root はグローバルの CSS 変数を宣言するのに便利です。

:hover などと同じく擬似クラスなんですね。

:root {} 内で定義した変数はグローバル変数になることは覚えておきます。

ところで、 E:root と書かれている記事もあったように、要素をくっつけて書くこともできるのでしょうか?
検証しました。

html(一部省略)

<html>
   :
  <h1>:rootとhtmlの検証</h1>
  <div>
    <p>あいうえお</p>
  </div>
   :
</html>

css

/* :rootよりも詳細度が高い */
html:root {
  color: pink;
}

/* html要素以外の要素を指定しても無効 */
p:root {
  color: green;
}

/* htmlよりも詳細度が高い */
:root {
  color: red;
}

html {
  color: blue;
}

p {
  color: green;
}

h1とp要素の文字色を確認しました。

p:roothtml:root を検証したところ、html:root は有効であることが分かりました。
要素の指定が入っている分、:root よりも詳細度が高いです。
おそらく E:root はhtml要素以外は使えないのだと思います。

html:root の使い所があるかは分かりませんが、使っているところを見たことがないので、個人的にはこれからも使わないです。

h1とp要素の文字色は、結果
h1:pink → html:rootcolor の指定がh1要素に継承された
p:green → 直接の要素指定によりp要素に継承されたpinkがgreenに上書きされた

でした。

検証したプロパティが color なのでここに「継承」が絡んでいて少しややこしいですが、 そもそもルート要素には継承するようなプロパティを設定することがほとんどだと思います。

そこで :roothtml どちらを使うかですが、好みの問題な気がしました。

カスタムプロパティの設定は :root で、普通のプロパティの設定は html にしてみたり、どちらかで統一してみたり。
変にごちゃまぜに使わなければいいのかと思います。

かなり脱線しました。

変数の呼び出し

.class {
  property: var(--var_name);
}

var(--変数名);です。

変数の呼び出しは、親要素で定義した変数が対象なので、 :root で定義すればすべての要素から呼び出すことができます。

Sass関数内にCSSの変数を呼び出せない

sass変数をcss変数(カスタムプロパティ)に渡す方法 - Qiita

Sassでこの書き方は駄目だそうです。

body { color : darken(var(--color-primary), 10%); }

darken() はSass関数です。

ちなみによく使う calc()CSSの関数なのでCSS変数は使えます。

Sassの変数

Sassの変数についても定義と呼び出しについて調べました。

【Sass実践編】Sassを使いこなす第一歩、「変数」の書き方と使い方! : ビジネスとIT活用に役立つ情報

変数の定義

$var_name: value;

$変数名: カラーコードや単位付きの数値など;

です。

セレクタの外にグローバル変数として定義ができますし、特定のセレクタの中でローカル変数として定義もできます。

変数の値の後ろに !global を付けるとグローバル変数扱いになるそうです。

メディアクエリ内でSass変数は定義できない

メディアクエリ内の変数設定はなかったことになります。

Sass(SCSS)

$color: red;

p {
  color: $color;  // ウィンドウサイズの幅が767px以下でもred
}

@media screen and (max-width: 767px) {
 $color: blue;
  // メディアクエリの中で変数を呼び出せば適用される
  // p {
  //   color: $color;
  // }
}

コンパイルcolor の値が決まりますが、メディアクエリは動的なので、この時点では青文字になるかどうかは分かりません。
よって color: blue; にはなりません。

メディアクエリの中で変数を呼び出せば適用されますが、↑この書き方はまるでSassの恩恵を受けていないので書かないほうがいいです。

ここはmixinを使って書くべきなのでしょうね。

一連の書き方が丁寧に載っていました。

【Sass】mixinでメディアクエリを管理する方法【応用編】 - TechnoBlog(テクノブログ)

変数の呼び出し

selector {
  property: $var_name;
}

プロパティの値の一部として変数を呼び出す場合は #{$var_name} と書きます。
これをインターポレーション(補完)といいます。

background-image: url(#{bg-image-path});

sassファイルでCSS変数とSass変数両方使う理由

ここまで見てきてどちらも一長一短であることが分かりました。

CSS変数 Sass変数
変数の定義 --変数名: 値; 要素に対して(プロパティ):rootグローバル変数 $変数名: 値; セレクタの外でグローバル変数
変数の呼び出し var(--変数名) プロパティの値 $変数名 関数の引数、プロパティの値の一部として呼び出す場合は #{$変数名}
Sass関数内
メディアクエリ

ざっくりしているのでもう少し表に加えていきたいです。
(内容があっているかどうかは少し心配です)

例のHugoテーマのSASSファイルを見てみても、まずSass変数を定義して、CSS変数でも同じ変数を定義して使えるところでどちらかの変数を呼び出す、ということをしていました。

まだ釈然としませんが、Sass変数をメディアクエリなどで効率的に使う方法を学べばわかるようになるのではないかと思います。

これでSassファイルをしっかりと読んで、Hugoブログのcssカスタマイズを進めていきたいと思います。