CSS 変数 (カスタムプロパティ) の使い方とルール

CSS 変数とは

CSS 変数とは、正式には「カスケード変数のための CSS カスタムプロパティ (CSS custom properties for cascading variables)」と定義されています。従来の CSS では、変数は Sass や LESS のような CSS プリプロセッサを使わなければ利用できませんでしたが、多くのブラウザでサポートされたことにより利用可能になりました。ただし、Internet Explorer など一部のブラウザは対応していません。また、Edge はサポートしていますが、バグが多発している報告があるため、クロスブラウザでテストする場合は注意が必要です。もしも非対応ブラウザも含めてサポートする場合、後述する @supports ブロックを使う方法があります。

CSS 変数をサポートする主要ブラウザ
Internet Explorer Icon
Internet Explorer
Edge Icon
Edge
Firefox Icon
Firefox
Chrome Icon
Chrome
Safari Icon
Safari
Chrome Icon
Chrome for Android
Safari Icon
Safari for iOS
×

今まで CSS は変数が使えなかったため、サイズや色などのプロパティ値をそれぞれのセレクタに直接定義していました。そのため何かを変更するための修正コストが大きく、メンテナンス性が悪い問題点がありました。特にチーム開発など、複数人で CSS をメンテナンスしている場合、CSS 自体が破綻する原因にもなっていました。

CSS 変数は、それらの問題点を改善するための仕様です。最初に CSS 変数にプロパティ値を定義すれば、それぞれのセレクタには変数を設定するだけで値が適用されるようになります。変数を定義、および使用するルールとしては、以下のとおりです。

  • 変数の定義は :root セレクタで行う
  • 変数の先頭には -- (ハイフン 2 つ) を付ける
  • 変数の呼び出しには var() 関数で行う
  • 変数は大文字・小文字の区別する
  • 変数は別の値が設定された場合、要素の子要素は新しい値を継承する
:root {
    --color-red: red;
}

.hoge {
    color: var(--color-red);
}
CSS 変数の定義と設定する例

var() 関数 は変数が未定義であった場合に備えて、第二引数にフォールバック値も設定できます。ただし上記の例のとおり、フォールバック値は省略が可能です。下記の例は、--color-red が未定義である場合、blue にフォールバックされます。

.hoge {
    color: var(--color-red, blue);
}
CSS 変数の定義と設定する例

CSS 変数には、CSS と同じようにプロパティ値を設定できるため、単位ありの数値、単位なしの数値、文字列などが設定できます。下記のようにマスターとなる値を定義しておけば、将来的に変更になった場合でも適用しているすべてのセレクタを修正する必要はなく、:root に定義された変数のみ修正すれば良いことになります。

:root {
  --def-font-size: 100 %;
  --def-line-height: 1.5;
  --def-background: #fff;
}
CSS 変数の定義と設定する例

更に CSS 変数は CSS 変数を使って定義することも可能です。下記の例は、赤色と青色のグラデーションを実現するために CSS 変数を使用しています。

:root {
  --color-red: red;
  --color-blue: blue;
  --def-gradient: linear-gradient(var(--color-red), var(--color-blue: blue));
}
CSS 変数の定義と設定する例

CSS 変数は別の値が設定された場合、要素の子要素は新しい値を継承します。CSS は他のセレクタでも値の変更が可能であり、変更された場合は対象の要素の子要素は新しい値を継承します。これは、CSS 変数のスコープに関係しています。:root で定義された変数はグローバルなスコープになり、他のセレクタで変更された場合は対象の要素の子要素はローカルなスコープになります。

/* CSS 側 */
:root {
  --color-text: red;
}
.blue {
  --color-text: blue;
}
p {
  color: var(--color-text);
}

<!-- HTML 側 -->
<p>red text</p>
<div class="blue">
  <p>blue text</p>
</div>
CSS 変数の定義と設定する例

CSS 変数は、Javascript でも getPropertyValue を指定することで変数の値を取得できます。

/* CSS側 */
.sidebar {
  --left-pos: 100px;
}

/* Javascript側 */
// cache the element you intend to target
const sidebarElement = document.querySelector('.sidebar');

// cache styles of sidebarElement inside cssStyles 
const cssStyles = getComputedStyle(sidebarElement);

// retrieve the value of the --left-pos CSS variable
const cssVal = String(cssStyles.getPropertyValue('--left-pos')).trim(); 

// log cssVal to print the CSS 
// variable's value to the console: 100px 
console.log(cssVal);
CSS 変数の定義と Javascript からの取得する例

Javascript から CSS 変数の値を変更するには以下のように設定します。

sidebarElement.style.setProperty('--left-pos', '200px');
Javascript から CSS 変数を設定する例

CSS 変数が非対応ブラウザを含めたクロスブラウザ対応を行う場合、@supports ブロックを使って回避する方法があります。@supports ブロックとは、CSS の機能をサポートしているかどうかを判別するための機能クエリです。以下の例では、非対応ブラウザが @supports ブロックをサポートしているかどうか判別しています。また、var() 関数にフォールバック値を設定しておけば安全性が高まり、レガシーブラウザにも対応できます。以下の例で sectionの要素は、CSS 変数が対応しているモダンブラウザの場合は青色文字になり、非対応のレガシーブラウザでは灰色文字になります。

section {
  color: gray;
}

@supports(--css: variables) {
  section {
    --my-color: blue;
    color: var(--my-color, 'blue');
  }
}
@supports ブロックを使った CSS 変数を設定する例

CSS 変数の仕様は、あくまでも今までの問題の改善であり解決ではない点に注意してください。どのような場合においても、これらの機能に頼りすぎて複雑化すれば CSS 全体が破綻してしまうリスクはなくなっていません。CSS 変数はこれまでのメンテナンスに選択肢が増えただけに過ぎず、どのように CSS を管理していくかが重要になります。

calc 関数の使い方

calc() 関数とは、CSS で数学演算を行うことができる関数で、標準的なブラウザはすべてサポートしています。calc() 関数では以下のように異なる単位での四則演算が可能です。

calc 関数をサポートする主要ブラウザ
Internet Explorer Icon
Internet Explorer
Edge Icon
Edge
Firefox Icon
Firefox
Chrome Icon
Chrome
Safari Icon
Safari
Chrome Icon
Chrome for Android
Safari Icon
Safari for iOS
.content {
    width: calc(100% - 200px);
}
calc() 関数を使った数学演算を行う例

Sass や LESS などの CSS プリプロセッサでも値の計算は行なえますが、calc() 関数とは根本的にことなります。CSS プリプロセッサの計算された値はブラウザに依存しない静的な値であるのに対して、calc() 関数はブラウザ依存の動的な値です。つまり、画面のリサイズによって Viewport が変更されても再計算により追従することができます。もしも CSS プリプロセッサで単位の異なる値を calc() 関数として出力する場合は、以下のようになります。

/* NG */
$var: 300px;
.content {
    width: calc(100% - $var); /* → width: calc(100% - $var); */
}

/* OK */
$var: 300px;
.content {
    width: calc(100% - #{$var}); /* → width: calc(100% - 300px); */
}
CSS プリプロセッサで calc() 関数を出力する例

calc() 関数はサイズ、幅、高さ、角度、時間など、何かしらの単位が必要なプロパティ値に利用できます。ただし、演算子の前後はスペースで区切らなければ有効にならないため注意が必要です。

.content {
    width: calc(100% - 200px); /* OK */
    height: calc(100%- 200px); /* NG */
}
calc() 関数を使った数学演算を行う例

calc() 関数は、特にレスポンシブデザインにおいて効果を発揮します。例えば、2 カラム構成でサブコンテンツの width300px 必要で、残りはメインコンテンツにしたい場合、以下のように指定できます。

.maincontent {
    width: calc(100vw - 300px);
}
.subcontent {
    width: 300px;
}
calc() 関数を使った数学演算を行う例

CSS 変数と calc 関数の組み合わせ

CSS 変数と calc() 関数を組み合わせることで、より柔軟な計算ができるようになります。例えば、CSS 変数で定義した値のマイナス値が欲しい場合、以下のような方法になります。

:root {
  --box-position: 100px;
}

/* NG */
.box {
  top: - var(--box-position);
}

/* OK */
.box {
  top: calc(-1 * var(--box-position));
}
CSS 変数と calc() 関数を使った例

上記の方法では、CSS 変数で定義されたマイナス値を取得するために calc() 関数で -1 を掛けています。CSS 変数は少し使いにくい点はありますが、calc() 関数を組み合わせることで今まで取得できなかった値を取得できることになります。アイデア次第では CSS 変数と calc() 関数を組み合わせることで、多くのレシピを生み出すことができます。

まとめ

CSS は「破綻しにくい CSS 設計手法と命名規則」でも書いたとおり、破綻しやすい言語仕様になっています。CSS 変数は、プロパティ値の扱いについて改善することができる仕様案ですが、それに頼ってコントロールを放棄することは本質的ではありません。CSS が破綻しないためには、厳密な管理とコントロールを行うようにしてください。それらを放棄した上で calc() 関数による計算で求めた値は、もはや正しい値と保証することはできません。そのため、便利な機能だからといって依存せず、CSS を管理するための選択肢のひとつとして扱ったほうが賢明です。

Category:
WEBデザイン
公開日:
更新日:
Pageviews:
1,141
Shares:
4
Tag:
CSS
レスポンシブデザイン
WEBデザイン
UX
コンテンツ制作
hatebu icon
hatebu