🐸

CSS カスタムプロパティ 1 基礎

2021/12/11に公開

CSS カスタムプロパティ (CSS 変数) とは

素の CSS で、変数感覚で扱えるプロパティ。複数箇所のスタイルを一元管理するのに便利。また、Dom のプロパティなので、値が動的にブラウザ表示に反映されるため JavaScript から値をコントロールすることで、様々な有用な処理ができる。

» 対応ブラウザ
※ IE 11 は非対応 (サポート終了の Polyfill はある)

習得すべき?

すでに様々な CMS、フレームワーク、ライブラリ等で使われており、自分のプロジェクトの CSS を最適化するためにはそれらを考慮した実装が必要となる。素の CSS なので廃れて無くなることもない。使いこなすと便利なはずなので習得しておいて損はない。

基本の基本

デモ1

  • :root 擬似クラスは、ドキュメント全体 (html 要素) に適用される
  • 使用したい箇所で var(--任意の名前)
  • 大文字と小文字を区別するので注意

Sass (SCSS) と CSS カスタムプロパティー

Sass 変数と CSS カスタムプロパティーとの違い

  • Sass など CSSプリプロフェッサーの場合、トランスパイルが必要で、変換後は固定値となる
  • CSS カスタムプロパティーは、ブラウザ上でそのまま動的に処理される。なので、JavaScript から get/setPropertyValue で直接参照でき、値を変更すれば即座にブラウザ表示に反映される

Sass 中でも使える

  • 素のCSSなので、Sass でも普通に使える
  • カスタムプロパティを Sass 変数に格納するのは不可。エラーに

Sass は不要となるか?

ならない。変数や計算は代替できるが、ネスト、ミックスイン、継承、ファイルの統合などはやはり必要なので、Sass との併用が現実的。状況により、Sass の代わりに PostCSS、CSSinJS (内部では CSS プリプロフェッサーを使用)、Tailwind CSS 等を採用する選択肢もある。

CSS カスタムプロパティに対応してないブラウザへの対応

Polyfill, @supports, PostCSS プラグイン

Polyfill

IE11 Polyfill サポート終了

<script>window.MSInputMethodContext && document.documentMode && document.write('<script src="https://cdn.jsdelivr.net/gh/nuxodin/ie11CustomProperties@4.1.0/ie11CustomProperties.min.js"><\/script>');</script>

@supports

@supports -MDN で以下のようにできるが、肝心の IE11 に対応していないので、CSS カスタムプロパティのフォールバックとして使うことはないだろう

.my-component {
  background-color: #82f263;
}
@supports (--css: variables) {
  .my-component {
    --myVariable: #ef62e6;
    background-color: var(--myVariable);
  }
}

PostCSS プラグイン

postcss/postcss-custom-properties - Github
変数を固定値として書き出し、サポートしているブラウザ向けに CSS カスタムプロパティを使った記述を書き出す。最終的な CSS が肥大化しそう

デフォルト値

var() 関数で

  • var(--primary, yellow); --primary が無ければ yellow を指定
  • 最初のカンマから関数の終わりまでが代替値とみなされる
    var(--hoge, aaa, bbb, ccc); "aaa, bbb, ccc" が代替値
  • var(--my-var, var(--my-background, pink)); のようにネストできるが、パフォーマンスが落ちるので避ける

env() でグローバルなスコープのデフォルト値を設定

env() - MDN 文書でグローバルなデフォルト値を設定できる。
例:env(safe-area-inset-top, 20px);\

無効な変数の場合

  • 継承値、なければプロパティの初期値が適用される

インラインCSSで上書きできる

  • <p class="primary" style="--primary-color: gold;"></p>

JavaScript で値の取得/セット

  • 従来の CSS プロパティの扱いと同じ
  • :root 疑似クラスで設定した値は、document.documentElement でアクセスできる
  • 実装
    • 任意のカスタムプロパティの値を取得
    • 任意のカスタムプロパティに値をセット
      • document.documentElement.style.setProperty('--color-pink', "pink"); 元々ないものも追加可能
        • この場合は、html 要素にインラインで埋め込まれる
          <html style="--color-pink: pink;">

その他 メモ

  • エディタの補完や表示のサポートはまちまち
  • var(--) と打つのがめんどい (→ コードスニペットで展開)

メディアクエリで

デモ2

  • メディアクエリ規則の中では使えない
  • メディアクエリ分岐で全体に影響するカスタムプロパティの値を変えたい場合は、:root をメディアクエリでスコープ分岐させる。
  • レスポンシブデザインで、サイズや余白調整に便利

スコープ

デモ3

  • :root 疑似クラスで文書全体がスコープに (≒グローバル変数)
  • プログラム言語の関数のスコープと同じ
    • 内側スコープ内を検索しあれば適用。無ければ一つ親の要素を探す。無ければそのさらに親の… :root まで探して無ければ無効値 (ブラウザ初期値) に
  • 従来のCSSの継承 (カスケード) そのまま

注意:値が継承される前に解決される

[CSS変数は値が継承される前に解決される - Zenn](https://zenn.dev/takamoso/articles/2021-04-tips#4.-css変数に関するクイズ]


CSS関数と併せて使う

デモ3

CSS アニメーションで、レイアウトで

今回は割愛

気をつけたいこと

複雑にし過ぎると見通しが悪くなる

入れ子(カスタムプロパティに別のカスタムプロパティの値をセット)にしたり、calc() 関数などを使った場合、複雑になりやすい。未来の自分や他人が見た時、最終的にどのような値になるのかを理解するのに労力を使うことになる。計算でいい感じにできることは多々あると思うが、あまり複雑になり過ぎないよう気をつけたい。

フレームワーク、CSS、ライブラリ等を使う場合

最適化する

フレームワーク、CMS、ライブラリ等が使用している CSS カスタムプロパティを把握した上で実装すること。例えば WordPress なら theme.json での設定で head タグ内にインラインで埋め込まれる CSS カスタムプロパティを把握し、同じ値は自分のCSSで値を直接定義せず、それらの CSS カスタムプロパティを使う。

プレフィックスを付ける

カスタムプロパティ名の重複はトラブルを招く可能性があるので、このプロジェクトで統一したプレフィックスを付けとくと無難。
--primary--XXX-primary
(例えば、WordPress は "--wp-"、Bootstrap は "--bs-" (変更可) と付いてる)

メモ:Sass なら、$prefix: hoge; --#{$prefix}-primary-color: red; のようにすれば後から容易に変更できる

まとめ

  • アイデア次第で色々できる (下の参考記事の応用例を参照)
    • 色・透明度、フォント、サイズ、余白、レイアウト(グリッド他)、表示/非表示、アニメーション

参考記事

わかりやすい解説

応用例

GitHubで編集を提案

Discussion