· 6分で読了

CSS変数とSASS変数

この記事は中国語から自動翻訳されたものです。翻訳によりニュアンスが失われている場合があります。

以前、CSS変数についての僕の考えを書いた記事があった。もともとこのプロパティにはあまり大きな期待を抱いていなかったし、SASSの変数に慣れていた僕にとって、このCSS変数はむしろ使い勝手の悪い中途半端なシステムのように見えていた。だが、もし君も同じように考えているなら、この記事 Why should you care Css variables を参考にしてみてほしい。

CSS変数は登場してからある程度の期間が経ち、ブラウザのサポート状況もそこまで悪くはない。おそらく皆も一度は、「これらの変数の機能はSASSでほぼすべて実現できるし、SASSの関数や型(list、map)と組み合わせれば、変数の柔軟性はさらに強力になるのではないか」と考えたことがあるだろう。

しかし、ここで僕が共有したいのは、CSS変数の真に優れているポイントがどこにあるのかということだ。

この記事では、すでに読者がCSS変数に関する基礎知識をある程度持っていることを前提としている。

ちなみに、この記事ではCSS変数の使い方を網羅的に書いているわけではないので、何かアドバイスや意見があればぜひ教えてほしい。いずれ時間を作って、より包括的な記事を書き直すつもりだ。

サポート状況

BrowserVersion
Chrome49
Firefox42
Safari9.1

custom property

プロパティのように振る舞わせたときに初めて、通常のプリプロセッサよりも強力になる

まず明確にしておきたいのは、CSSの仕様 において、変数(variable)は実際には custom property(カスタムプロパティ)と呼ばれているという点だ。これはどういう意味だろうか?「変数」と「プロパティ」で頭が混乱してしまうかもしれない。

焦る必要はない。つまりCSS変数を使う際には、単なるプログラミング的な「変数」としてではなく、通常のCSS「プロパティ」として捉えるべきだということだ。以下では、CSS変数の使い方についていくつか紹介していく。

なぜCSS変数を使うべきなのか

  • これらのプロパティを使うのにプリプロセッサは不要
  • initialinherit を使って階層構造を作ることができる。
  • ブラウザが必要なときに再レンダリングしてくれる
  • アクセス可能であり、JavaScriptを使って操作できる(後ほど説明する)

プロパティの特性

CSSプロパティである以上、当然ながら以下のような特性を持つ:

  • いわゆる initialinherit といった値が使える
  • 呼び出し方は var(--variable-name)
  • inline-style の中に記述できる
  • JSから値の取得や設定ができる

中でも最大の目玉は、inline-styleに書ける点と、JSと連携して値の取得・設定ができる点だ。これこそがSASSやLESSなどのCSSプリプロセッサとの最大の違いであり、CSSに新たな可能性をもたらしてくれる。さっそくいくつかの具体例を見ていこう。

:root {
  --mainColor: #abc;
  --subColor: #ccc;
}

h1 {
  color: var(--mainColor);
}

ここで :root に宣言された値はすべての要素に継承される。これこそが custom property の特性だ。

inline-style

プロパティなので、当然このように書くことができる。

<h1 style="color: var(--mainColor);">
  Hello, world
</h1>

一見すると大して珍しいことではないように思えるかもしれない。同じことはクラスとSCSS変数を組み合わせても実現できるからだ。しかし、これによってinline-styleを書く際の選択肢と可能性がさらに広がる。

react inline style

例えばReactにおいて、inline-styleを書く必要がある場面がある。しかし色の定義がSCSSの管理から外れてしまうため、往々にして非常に扱いづらくなる。カラーコードを直接ベタ書きして後から修正する羽目になるか、あるいはJS側で別途カラー変数テーブルを保持するか、もしくはカラー変数ごとにクラスを割り当てるのが関の山だった。

今はCSS変数があるため、非常に便利に使うことができる。

const styles = {
  heading: {
    fontSize: "14px",
    color: "var(--mainColor)",
  },
  warn: {
    color: "var(--warnColor)",
  },
}

const heading = ({ title }) => <h1 style={styles.heading}>{title}</h1>

※この記事ではCSS変数の紹介に焦点を当てているが、実際にはReactにおけるスタイリングの管理方法は他にも優れたアプローチが存在する。

grid

ガター(gutter)の設定も、今やCSS変数を使って実現できる。つまり、@media クエリを使って変数の値を切り替えることができるのだ。これは通常のプリプロセッサでは不可能なことである。

JSによる制御

JavaScriptを操作することで、CSS変数の値の設定や取得を簡単に行うことができ、ViewとJSの分離を実現できる。例えば、何らかの演出のためにJSで値を取得し、それをCSSに渡したいとする。従来であれば、JavaScriptで計算を行った後、その計算結果をinline-styleで要素に直接適用することが多かった。

しかし、それでは以下のような問題が生じる可能性がある:

  • その値が意図したものでなかったり、CSS側でその値に対してさらに独自の加工を加えたい場合がある。そうなるとJavaScriptのコードを修正し直さなければならず、非常に面倒だ。
  • inline-styleで直接値を書き込んでしまうため、通常のCSS側からは手出しができなくなる。

CSS変数が導入されたことで、値の設定や取得は極めて手軽になった。

値の取得
HTMLElement.style.getPropertyValue("--mainColor")
値の設定
HTMLElement.style.setProperty("--mainColor", "#abc")

したがって、イベントリスナーを登録して、注目している数値をCSS変数に流し込むことも当然可能だ。

const element = document.addEventListener("mousedown", e => {
  // some HTMLElement;
  element.style.setProperty("--pageX", e.pageX)
  element.style.setProperty("--pageY", e.pageY)
})
サポート状況の確認

現在のブラウザがCSS変数をサポートしているかどうかを確認したい場合は、CSS.supports の構文を使って判定できる。

CSS.supports('(--css: variables)') CSS.supports('not (--css: variables)')

今後の課題

変数を管理する方法が増え、JavaScriptから変数の値を設定するケースも出てくるため、これらの変数を扱う際にはより注意を払う必要がある。

  • 変数の宣言を一元管理する:グローバル変数は1つのファイルまたはディレクトリにまとめておくと、後のメンテナンスが楽になる。CSS変数を宣言する場合も同様だ。
  • JSから値を設定するための変数には、目印としてプレフィックス(接頭辞)を付けると良い。例えば --js-pageX などのように命名する。

結論

この記事では、CSS変数の使い方や活用シーンを紹介した。以前の僕もCSS変数は使いづらいと感じていたし、記述方法が見た目としてイマイチなうえ、便利な関数操作もないと思っていた。

しかし、CSS変数が「カスタムプロパティ(custom property)」であるという本質を理解すると、従来のCSSでは突破できなかった新たな可能性が見えてくる。SASSかCSS変数のどちらか一方を無理に選ぶ必要はない。むしろ両者を組み合わせることで、これまでにない強力な表現や設計を実現できるのだ。

関連記事

他のトピックを探索