CSS custom properties are a feature that allow you to declare variables directly in CSS and manage them dynamically, which helps improve design consistency and maintainability.
CSSのカスタムプロパティ(Custom Properties)とは、通称「CSS変数」と呼ばれる機能です。--変数名: 値;
という形式で定義することで、CSS内で定義した値を再利用しやすくなり、デザインの一貫性やメンテナンス性が向上します。
CSS
:root {
--main-color: #3498db; /* カスタムプロパティの定義 */
--main-padding: 16px;
}
.content {
color: var(--main-color); /* カスタムプロパティの呼び出し */
padding: var(--main-padding);
}
上記の例では、--main-color
や --main-padding
を自由に使い回すことができ、デザインを一元管理しやすくなります。
SassやLessなどのCSSプリプロセッサを使うと、同様に変数を使うことが可能です。ただし、プリプロセッサの変数はビルド時に静的に展開されるのに対し、CSSのカスタムプロパティは実行時にブラウザが解決する動的な性質を持ちます。
カスタムプロパティは、セレクタ内に --変数名: 値;
の形で定義します。
CSS
.selector {
--my-color: #ff0000;
--my-size: 2rem;
}
グローバルに使いたい場合はルートセレクタ(:root
)を使うことが一般的です。
CSS
:root {
--theme-color: #3498db;
}
定義したカスタムプロパティを使う際は、var(--変数名)
と書きます。
CSS
element {
color: var(--theme-color);
}
var()
関数の第2引数にフォールバック値を指定できます。カスタムプロパティが未定義または無効な場合に使用されます。
CSS
.element {
color: var(--unknown-color, #000000); /* 未定義なら#000000を使う */
}
:root
セレクタで定義されたカスタムプロパティは、基本的にどの要素からも参照可能です。サイト全体で共通のテーマカラーや余白サイズなどを管理するときに便利です。
カスタムプロパティは、定義された要素およびその子孫要素に継承されます。
CSS
.parent {
--local-color: #f1c40f;
}
.child {
color: var(--local-color); /* 親の定義を継承している */
}
ただし、別の階層で再定義すると、それ以降は再定義された値が使われます。これにより、コンポーネント単位で異なるテーマを適用したり、状態(ホバーなど)によって値を変更することができます。
ライトテーマ・ダークテーマなどをワンクリックで切り替えたい場合、カスタムプロパティが有効です。
CSS
:root {
--bg-color: #ffffff;
--text-color: #333333;
}
.dark-theme {
--bg-color: #333333;
--text-color: #ffffff;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
}
JavaScriptで document.body.classList.toggle('dark-theme');
のような切り替えを行うと、一気にダークモードへ変更でき、複数箇所で使用されている色指定を同時に更新できます。
メディアクエリやJavaScriptでカスタムプロパティを変化させることで、フォントサイズや余白を動的に変更できます。
CSS
:root {
--base-font-size: 16px;
}
@media (min-width: 768px) {
:root {
--base-font-size: 18px;
}
}
.text {
font-size: var(--base-font-size);
}
これにより、レスポンシブデザインでも変数を一箇所変更するだけでサイト全体のフォントサイズが整合的に変わり、管理が容易になります。
ボタンなどのUIコンポーネントに、カスタムプロパティを用いることで色・余白・ボーダーなどを一括管理できます。たとえば、複数のバリエーション(プライマリ・セカンダリ・アクセントなど)を一つのコンポーネントクラスで切り替えたい場合に、カスタムプロパティが役立ちます。
CSS
.btn {
--btn-bg: #3498db;
--btn-color: #ffffff;
--btn-padding: 0.5em 1em;
background-color: var(--btn-bg);
color: var(--btn-color);
padding: var(--btn-padding);
border: none;
border-radius: 4px;
}
.btn--secondary {
--btn-bg: #7f8c8d;
--btn-color: #ecf0f1;
}
.btn--secondary
では、背景色と文字色だけを上書きすることで、プライマリボタンとの差別化が可能になります。
CSSカスタムプロパティは、JavaScriptから動的に値を書き換えることができます。DOM要素の style
オブジェクトか、setProperty()
メソッドを使って操作します。
HTML
<button id="changeTheme">テーマ変更</button>
<div class="content">...</div>
CSS
:root {
--content-padding: 16px;
}
.content {
padding: var(--content-padding);
}
JavaScript
document.getElementById('changeTheme').addEventListener('click', () => {
document.documentElement.style.setProperty('--content-padding', '32px');
});
上記のように setProperty('--content-padding', '32px')
を呼び出すと、即座にCSSのプロパティが更新され、ブラウザ上の要素が再描画されます。
transform
プロパティやrequestAnimationFrame
などを駆使しながら慎重に設計する必要があります。--color-primary
や --layout-main-padding
のように、用途や領域を示すプレフィックスをつけると管理しやすくなります。.dark .header
と .light .header
で異なるカスタムプロパティを定義することで、要素ごとのテーマを細かく制御できます。CSS
.light .header {
--header-bg: #f8f9fa;
}
.dark .header {
--header-bg: #343a40;
}
.header {
background-color: var(--header-bg);
}
主要ブラウザ(最新のChrome、Firefox、Safari、Edge)はほとんどサポートしていますが、Internet Explorer 11 など古いブラウザではカスタムプロパティをサポートしていません。
もしレガシーブラウザにも対応したい場合は、PostCSSやSassなどでフォールバックを用意するか、IE11では別の手段を採用するといった対策が必要になります。
--変数名: 値
で定義し、var(--変数名)
で参照する。--color-primary-lihter
、--color-primary-darker
のように、基準となる色(--color-primary
)から派生したカラーセットを構築することで、配色体系を作りやすくなります。calc()
関数内でも var()
を使えるので、動的な余白やサイズ計算を行う際に便利です。CSS
:root {
--base-space: 10px;
}
.container {
padding: calc(var(--base-space) * 2);
}
transition
を設定すると、変化がスムーズにアニメーションします。コンポーネントごとのインタラクションをより魅力的に表現できます。CSSカスタムプロパティは、単なる「変数」としての使い方にとどまらず、動的で柔軟なスタイリングを可能にする重要なツールです。複雑なデザインシステムやテーマ機能を扱う際にも、コードの保守性を高めながら柔軟に拡張できる利点があります。
初めて触れる方は、まずは共通の色やフォントサイズを変数化することから始め、慣れてきたらテーマの切り替えやJavaScriptとの連携といった応用へ進むとよいでしょう。中級者以上の方は、より複雑なコンポーネント管理や名前空間設計などに取り組み、CSSカスタムプロパティを活用することで、よりスマートで再利用性の高いスタイル設計が行えます。
ぜひプロジェクトに導入して、その便利さを体感してみてください!