CSSカスタムプロパティとSassの違い 完全整理 どっちを使うか迷う時間を終わらせる

Web技術

CSSの変数って結局どれを使えばいいのか。現場で一回は迷います。

CSSカスタムプロパティ(var)が出てきてから、Sassの変数やmixinの立場が変わった。変わったのに、昔の成功体験もまだ強い。結果として、プロジェクトごとに流派が分かれる。あるあるです。

ただ、どっちが上とか下とか、そういう話にしたくない。役割が違う。強みが違う。合う場面も違う。そこを押さえれば、迷いは減ります。

この記事は、CSSカスタムプロパティとSassの違いを、実務の匂いがする視点で整理します。なぜ今この比較が必要なのか。どう書くと事故が減るのか。メリットとデメリット。どこで混ぜるべきか。混ぜるときの地雷まで。

読んだあとに、あなたのプロジェクトの設計が少しだけ整う。そんな方向でいきます。

  1. なぜ今さら「違い」を整理する必要があるのか
  2. まず前提: CSSカスタムプロパティとSassは同じものではない
  3. CSSカスタムプロパティとは: ブラウザで動く変数
    1. カスタムプロパティの強いところ
    2. カスタムプロパティの弱いところ
  4. Sassとは: CSSを作るための言語
    1. Sassの強いところ
    2. Sassの弱いところ
  5. できること できないことを一発で見分ける表現
    1. CSSカスタムプロパティが得意
    2. Sassが得意
  6. メリットとデメリットをもう少し実務寄りに掘る
    1. カスタムプロパティのメリット 実務編
    2. カスタムプロパティのデメリット 実務編
    3. Sassのメリット 実務編
    4. Sassのデメリット 実務編
  7. やり方: どっちをどう使うかの現実的な答え
    1. おすすめの役割分担(現場向け)
  8. やり方: ダークモードとユーザー設定で差が出る場面
  9. やり方: レスポンシブの値はどっちに持つべきか
    1. カスタムプロパティでレスポンシブを扱う例
    2. Sassでレスポンシブを扱う例
  10. 地雷: 両方使うときに起きがちな事故
    1. 地雷1: 同じ概念をSass変数とCSS変数で二重管理
    2. 地雷2: カスタムプロパティを増やし過ぎて設計が崩れる
    3. 地雷3: 変数のスコープが意図せず漏れる
    4. 地雷4: Sassのネストが深くなって上書き合戦
  11. メリット比較: どっちが速い どっちが軽い
  12. デメリット比較: 保守とチーム運用で差が出る
  13. 実務でのおすすめ構成: 迷いを減らすテンプレ
    1. 1) デザイントークンはCSSカスタムプロパティ
    2. 2) レイアウトの再利用はSassのmixin
    3. 3) コンポーネント固有の可変値はコンポーネント内のカスタムプロパティ
    4. 4) 変数命名のルールを決める
  14. 読者に有益な追加情報: どっちを選ぶかで迷った時の質問
  15. カスタムプロパティの小技: 使うと仕事が少しだけ楽になる
    1. clampと組み合わせてタイポを滑らかに
    2. JSでテーマを切り替える時も素直
  16. Sassの小技: 現場で効く地味な整え方
    1. メディアクエリはmixinで統一
    2. mapでデザイントークンを管理しやすくする
  17. 最後に: 個人の偏見 どっちが好きか

なぜ今さら「違い」を整理する必要があるのか

理由は単純で、CSSが強くなったからです。

昔は、変数もネストも計算も、だいたいSassの担当だった。CSSは素朴で、頼れるのはプリプロセッサ。ところが今は、CSS側に変数がある。計算もある。条件分岐っぽいことも増えた。しかもブラウザ上で動く。

それでもSassが不要になったかというと、そうでもない。ビルド時に出来ることが強いし、コードベースを整理する道具として優秀です。

だから現場で起きるのがこのパターン。

  • 全部Sassで書いてきたが、ダークモードが面倒になった
  • CSS変数を導入したが、設計が崩れて変数だらけになった
  • 両方混ぜたら、どこが真実の値なのか分からなくなった

このあたりで人は疲れます。疲れると、雑にコピペして増殖が始まる。最悪のループ。

なので、ここで一度、役割分担を決めておく。これが効きます。

まず前提: CSSカスタムプロパティとSassは同じものではない

似ているようで、根っこが違います。

CSSカスタムプロパティは、ブラウザが解釈して、実行時に値が決まる変数です。DOMやCSSの状態によって値が変わる。生きている変数。

Sassは、ビルド時にCSSを生成するための道具です。変数もmixinもfunctionも、最終的には普通のCSSに変換されます。生成のための変数。

この違いが、そのままメリットとデメリットになる。ここが肝。

CSSカスタムプロパティとは: ブラウザで動く変数

カスタムプロパティはこう書きます。

:root {
  --color-primary: #1e40af;
  --space-4: 16px;
}

.button {
  background: var(--color-primary);
  padding: var(--space-4);
}

ポイントは、値がCSSのカスケードに乗ること。つまり、スコープがある。上書きできる。状況で変えられる。

カスタムプロパティの強いところ

  • 実行時に値を切り替えられる
  • カスケードと継承で上書き出来る
  • JSから書き換え可能
  • テーマ切り替え(ダークモード等)に強い
  • コンポーネント単位で局所的に変えられる

たとえば、ダークモード。これが一番分かりやすい勝ち筋です。

:root {
  --bg: #ffffff;
  --fg: #111111;
}

[data-theme="dark"] {
  --bg: #0b0b0b;
  --fg: #f2f2f2;
}

body {
  background: var(--bg);
  color: var(--fg);
}

これ、Sassの変数だけでやろうとすると、基本的にはCSSを二系統生成するか、クラスを大量に作る方向になります。出来なくはないが、しんどい。

カスタムプロパティの弱いところ

  • 型や単位のミスが実行時まで気づきにくい
  • ビルド時最適化(未使用削除など)の設計が必要
  • 変数の依存関係が複雑になると追えなくなる
  • 値の最終形がデバッグ前提になることがある

カスタムプロパティは便利です。便利だからこそ、雑に増えます。増えると、意味が薄い変数が増殖する。space-13みたいなやつ。誰が使うの、それ。そういう未来が見える。

なので、設計が大事。ここは本当に大事。言葉を変えると、ルールがないと破綻しやすい。

Sassとは: CSSを作るための言語

Sassはこういうやつです。

$primary: #1e40af;
$space-4: 16px;

.button {
  background: $primary;
  padding: $space-4;
}

これが最終的に普通のCSSになります。ブラウザにはSassの変数は残りません。ここがカスタムプロパティとの決定的な差です。

Sassの強いところ

  • ビルド時に計算や分岐、ループが出来る
  • mixinやfunctionで再利用設計がしやすい
  • ファイル分割やモジュール化が得意
  • タイポや単位ミスをビルドで弾けることがある
  • 既存資産が多い(現場での運用ノウハウが豊富)

例えば、ユーティリティクラスを自動生成したい。こういう場面でSassは強い。

$spaces: (0, 4, 8, 12, 16, 24, 32);

@each $s in $spaces {
  .mt-#{$s} { margin-top: #{$s}px; }
}

CSSでも似たことは出来るようになってきましたが、プロジェクトの整備としてはSassのほうが扱いやすい場面が多い。

Sassの弱いところ

  • 実行時に値を切り替えられない(生成されたCSSは固定)
  • テーマ切り替えやユーザー設定に弱い
  • ビルド環境が必須
  • ネスト多用でCSSが肥大化しやすい

Sassのネストは麻薬です。気持ちいい。だが深く潜ると戻れない。結果としてセレクタが太り、上書きが増え、メンテが地獄になる。何度も見た。

できること できないことを一発で見分ける表現

ここで、判断を雑にしていい基準を置きます。

CSSカスタムプロパティが得意

  • ダークモードやテーマ切り替え
  • コンポーネントごとの見た目の変化(親で上書き)
  • JS連動のアニメーションやインタラクション(値を動かす)
  • メディアクエリやコンテナクエリで値を切り替える

Sassが得意

  • 設計をパッケージ化する(mixin, function)
  • ループやマップでCSSを生成する
  • 共通の計算やフォーマットを強制する
  • 大規模なファイル分割と整理

カスタムプロパティは動的。Sassは生成。これだけ覚えておけば、半分は勝ちです。

メリットとデメリットをもう少し実務寄りに掘る

理屈は分かった。で、現場でどんな差が出るのか。

カスタムプロパティのメリット 実務編

  • デザインシステムのテーマを差し替えやすい
  • 白黒だけじゃなく、ブランドカラー別の展開がしやすい
  • コンポーネントを別案件に持って行きやすい
  • CSSだけで変更が完結しやすい

カスタムプロパティのデメリット 実務編

  • 命名が雑だと破綻する(意味のない変数地獄)
  • 値の追跡に慣れていない人が迷子になる
  • 最終値がどこで決まったか、慣れるまで時間がかかる

あなたのチーム、変数の命名規則ありますか。カオスになっていませんか。

Sassのメリット 実務編

  • 運用ルールをコードで押し付けられる
  • mixinで統一したレイアウトやタイポが作りやすい
  • 共通設計の再利用が楽(特に複数案件)
  • ビルドで失敗が見えることがある

Sassのデメリット 実務編

  • ビルド環境の維持が必要(Viteなどとセット運用)
  • テーマ切り替えが苦手
  • 設計をミスるとCSSが増えやすい

個人的には、Sassの最大の価値はmixinでも変数でもなく、チームの癖を一定に整える道具になれるところ。ここに偏愛があります。

やり方: どっちをどう使うかの現実的な答え

一番現実的なのは、両方使うことです。

ただし混ぜ方が雑だと、事故が増えます。なので、混ぜるなら役割分担を決める。

おすすめの役割分担(現場向け)

  • Sass: ファイル構造、mixin、function、生成系、設計の土台
  • CSSカスタムプロパティ: テーマ、可変値、コンポーネントの微調整、実行時の差し替え

例を出します。Sassで設計を作って、値はカスタムプロパティに逃がす。これが一番バランスが良いと感じています。

/* tokens.css */
:root {
  --radius: 12px;
  --shadow: 0 10px 30px rgba(0,0,0,.08);
  --space-2: 8px;
  --space-3: 12px;
}

/* component.scss */
.card {
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-3);
}

これなら、テーマ切り替えでradiusやshadowを変えられる。しかもコンポーネント側は読みやすい。

逆に、Sass変数で全部固定してしまうと、あとからダークモードやテーマ展開の要求が来たときに詰みやすい。あるあるです。

やり方: ダークモードとユーザー設定で差が出る場面

テーマ切り替えは、カスタムプロパティの主戦場です。

:root {
  --bg: #ffffff;
  --fg: #111111;
  --link: #1e40af;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b0b0b;
    --fg: #f2f2f2;
    --link: #93c5fd;
  }
}

この書き方は、ユーザーのOS設定に寄り添えます。押し付けない。これが良い。

Sassでこれをやるなら、dark用のCSSを別で出すか、darkクラス前提のCSSを生成する。どちらも出来るが、運用コストが上がりやすい。

やり方: レスポンシブの値はどっちに持つべきか

ここが揉めポイントです。現場でよくある。

ブレイクポイントやfont-sizeのスケール。Sassで完結したくなる。だが、カスタムプロパティを使うと後から調整しやすい。

カスタムプロパティでレスポンシブを扱う例

:root {
  --container: 1100px;
  --space: 16px;
}

@media (max-width: 767px) {
  :root {
    --container: 92vw;
    --space: 12px;
  }
}

.wrapper {
  width: min(100%, var(--container));
  padding-inline: var(--space);
}

こういうの、後から調整が速い。特に運用で微調整が多いサイトに向く。

Sassでレスポンシブを扱う例

$bp-sp: 767px;

@mixin sp {
  @media (max-width: $bp-sp) { @content; }
}

.wrapper {
  width: min(100%, 1100px);
  padding-inline: 16px;

  @include sp {
    width: 92vw;
    padding-inline: 12px;
  }
}

読みやすさはSass側が勝ちやすい。チームの好みも出ます。僕はmixinでメディアクエリを統一するのが好きだ。

地雷: 両方使うときに起きがちな事故

混ぜるなら、ここを避けたい。

地雷1: 同じ概念をSass変数とCSS変数で二重管理

$primaryと–primaryが両方存在する。しかも微妙に値が違う。はい終わり。

色や余白など、意味が同じなら、どちらかが真実の値になるように決める。ここは絶対に必要。

地雷2: カスタムプロパティを増やし過ぎて設計が崩れる

変えたいから作る。分かる。だが、全部を変数にすると読めなくなる。

個人的ルールとしては、デザイントークンとして意味があるものだけを変数にします。コンポーネント固有の一回きりの値は、普通に直書きする。割り切り。

地雷3: 変数のスコープが意図せず漏れる

カスタムプロパティはカスケードに乗る。便利。だが漏れる。

親で上書きしたつもりが、想定外の子にも影響することがある。これを防ぐには、コンポーネントのルートで変数を閉じる設計が効く。

.card {
  --card-bg: #fff;
  background: var(--card-bg);
}

.card.is-warning {
  --card-bg: #fff7ed;
}

card専用の変数をcard内で完結させる。こうすると事故が減ります。

地雷4: Sassのネストが深くなって上書き合戦

ネストは深くするほどCSSの詳細度が上がる。上がると上書きが必要になる。上書きが増えると、また詳細度を上げる。地獄の階段。

ネストは2段くらいで止める。これも僕の偏見。だが、だいたい当たる。

メリット比較: どっちが速い どっちが軽い

よくある疑問に答えます。

CSSカスタムプロパティはブラウザで解決されるので、動的に変えられる。そのぶん、値の評価が実行時に行われます。ただ、普通のサイトでこれがボトルネックになることは多くない。よほどアニメーションで大量に変数を動かすとか、極端なケースです。

Sassはビルドで固定されるので、実行時の負担は少ない。その代わり、CSSが増えやすい設計だとファイルサイズが太る。これが実害として出やすい。

つまり、速度や軽さで単純に勝敗はつかない。設計と運用が勝敗を決めます。

デメリット比較: 保守とチーム運用で差が出る

忙しい現場だと、保守性の差が一番効きます。

Sassは、設計の枠を作りやすい。mixinやfunctionで統一ができる。新しい人が入っても、ルールに乗せられる。

カスタムプロパティは、自由度が高い。自由は便利。だが、自由は破綻も呼ぶ。命名とスコープ、用途の整理が出来ていないと、数か月後に読めなくなる。

あなたの案件、半年後に別の人が触る可能性ありますか。未来の誰かを助けるなら、Sassの枠組みは効く。そう感じています。

実務でのおすすめ構成: 迷いを減らすテンプレ

僕がよく採用する形を置きます。好みです。

1) デザイントークンはCSSカスタムプロパティ

  • 余白
  • 角丸
  • フォントサイズの段階

2) レイアウトの再利用はSassのmixin

  • メディアクエリ
  • コンテナ幅
  • よく使うレイアウトパターン

3) コンポーネント固有の可変値はコンポーネント内のカスタムプロパティ

card専用、button専用の変数を閉じる。漏らさない。

4) 変数命名のルールを決める

ルールがないと増える。増えると死ぬ。これは断言。

例として、グローバルは–color-xxxや–space-xxx。コンポーネント専用は–card-xxxや–btn-xxx。こういう感じ。

読者に有益な追加情報: どっちを選ぶかで迷った時の質問

迷ったら、この2つを自分に聞くと良い。

この値は、実行時に変わる必要があるか。テーマや状態で変わるか。変わるならカスタムプロパティの出番。

この書き方は、チームのルールとして固定したいか。繰り返し使う形か。固定したいならSassの出番。

そしてもう一つ。あなたは今、変数を増やしたいだけではありませんか。

変数を増やすと気持ちいい。整理した気になる。だが整理とは違う。名前の付いた散らかしになることもある。ここは自戒です。

カスタムプロパティの小技: 使うと仕事が少しだけ楽になる

clampと組み合わせてタイポを滑らかに

:root {
  --fs-1: clamp(14px, 1.2vw, 16px);
  --fs-2: clamp(18px, 1.8vw, 22px);
}

body { font-size: var(--fs-1); }
h2 { font-size: var(--fs-2); }

これ、後から調整がラクです。Sassで計算して固定値を出すより、運用で強いと感じる場面が多い。

JSでテーマを切り替える時も素直

document.documentElement.dataset.theme = "dark";

これでCSS側が反応する。CSSが主体になる。好きなやり方です。

Sassの小技: 現場で効く地味な整え方

メディアクエリはmixinで統一

$bp-sp: 767px;

@mixin sp {
  @media (max-width: $bp-sp) { @content; }
}

書き方が揃うと、レビューが速い。これが大きい。

mapでデザイントークンを管理しやすくする

$spaces: (
  1: 4px,
  2: 8px,
  3: 12px,
  4: 16px
);

@function space($n) {
  @return map-get($spaces, $n);
}

.box { padding: space(4); }

こういう道具立てがあると、場当たりの値が減る。結果としてCSSが痩せます。

最後に: 個人の偏見 どっちが好きか

僕はどっちも好きです。ずるい答え。

ただ、カスタムプロパティの登場で、CSSはもうプリプロセッサの補助輪を外し始めたと思っています。テーマ切り替え、状態管理、設計の柔軟性。これは強い。

一方で、Sassのmixinやfunctionで設計を整えるのは、チーム開発の現実に刺さる。ルールで守る。速さと安全の話。

なので、僕の推しは役割分担です。Sassで骨格を作り、カスタムプロパティで血を通わせる。そんな感じ。

あなたの現場はどっち寄りですか。ダークモードやブランド展開が増えそうなら、カスタムプロパティに寄せると楽になるかもしれない。複数人で保守するなら、Sassの枠で整えると助かるかもしれない。迷いはゼロにならないが、迷う時間は減らせます。

(Visited 2 times, 1 visits today)
タイトルとURLをコピーしました