CSS @propertyでカスタムプロパティにアニメーションをかけてみた
CSSカスタムプロパティ(CSS変数)って便利ですよね。でも、transitionやanimationでスムーズに変化させようとすると、うまくいかないんですよね。
今回は、CSS @property を使ってカスタムプロパティにアニメーションをかける方法を試してみました。
▶ サンプルページを見る(グラデーション色変化・回転・カウントアップのインタラクティブデモ)
目次
CSS変数は通常トランジションできない
まず、普通にCSS変数をtransitionで変化させようとしてみます。
:root {
--bg-color: #3498db;
}
.box {
background: var(--bg-color);
transition: --bg-color 0.5s ease;
}
.box:hover {
--bg-color: #e74c3c;
}これだと、ホバーしても色がパッと切り替わるだけで、スムーズなアニメーションにはなりません。ブラウザはCSS変数の中身がどんな型の値なのか分からないので、補間(中間値の計算)ができないんですよね。
@propertyで型を定義するとアニメーション可能になる
@propertyは、CSSカスタムプロパティに「型情報」を与える仕組みです。もともとCSS Houdiniの仕様から生まれたもので、型が分かればブラウザが中間値を計算できるようになります。
書き方はこんな感じです。
@property --bg-color {
syntax: "<color>";
inherits: false;
initial-value: #3498db;
}3つのディスクリプタを指定します。
- syntax: プロパティの型を定義します。
<color>、<length>、<number>、<angle>、<percentage>などが使えます - inherits: 親要素から値を継承するかどうかです。
trueまたはfalseを指定します - initial-value: 初期値です。syntaxで指定した型に合った値を書きます
この3つはすべて必須です。どれか一つでも抜けるとエラーになるので注意ですね。
実例1: グラデーションの色をアニメーション
通常、background: linear-gradient(...)はトランジションできません。でも@propertyを使えば、グラデーション内の色をスムーズに変化させられます。
@property --gradient-start {
syntax: "<color>";
inherits: false;
initial-value: #3498db;
}
@property --gradient-end {
syntax: "<color>";
inherits: false;
initial-value: #2ecc71;
}
.gradient-box {
background: linear-gradient(135deg, var(--gradient-start), var(--gradient-end));
transition: --gradient-start 0.8s ease, --gradient-end 0.8s ease;
}
.gradient-box:hover {
--gradient-start: #e74c3c;
--gradient-end: #f39c12;
}ホバーすると、青→緑のグラデーションが赤→オレンジにスムーズに変わります。グラデーション自体はtransitionできませんが、中の色を個別に@propertyで定義してあげることで解決できるんですよね。
実例2: 角度を変えてグラデーションを回転
角度も@propertyで型定義すれば、アニメーションできます。グラデーションをぐるぐる回転させてみました。
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.rotating-gradient {
background: conic-gradient(from var(--angle), #f06, #9f0, #0ff, #f06);
animation: rotate-gradient 3s linear infinite;
}
@keyframes rotate-gradient {
to {
--angle: 360deg;
}
}conic-gradientの開始角度を@propertyで定義して、@keyframesで0degから360degまで回しています。これだけでグラデーションがくるくる回転するアニメーションが作れます。CSSだけで実現できるのが良いですね。
実例3: 数値のカウントアップアニメーション
<integer>型を使うと、数値のカウントアップも@propertyで実現できます。JavaScriptを使わずにCSSだけで数値をカウントアップさせてみました。
@property --num {
syntax: "<integer>";
inherits: false;
initial-value: 0;
}
.counter {
animation: count-up 2s ease-out forwards;
counter-reset: num var(--num);
}
.counter::after {
content: counter(num);
}
@keyframes count-up {
to {
--num: 100;
}
}ポイントはcounter-resetで--numの値をCSSカウンターに渡しているところです。@propertyで<integer>として定義しているので、0から100まで整数で補間されます。結果として、画面上で数字が0から100にカウントアップしていくアニメーションになります。
ブラウザ対応状況
@propertyのブラウザ対応状況をまとめてみました(2026年3月時点)。
- Chrome: 85以降で対応
- Edge: 85以降で対応
- Safari: 15.4以降で対応
- Firefox: 128以降で対応
主要ブラウザはすべて対応済みですね。Firefoxの対応が2024年と比較的最近ですが、現在はほぼ問題なく使えます。
@supportsでフォールバックを用意する
とはいえ、古いブラウザも考慮する場合はフォールバックを用意しておくと安心です。@supportsを使って、@propertyに対応しているかどうかを判定できます。
/* フォールバック: 通常のトランジション */
.box {
background: #3498db;
transition: background 0.5s ease;
}
.box:hover {
background: #e74c3c;
}
/* @property対応ブラウザ向け */
@supports (background: paint(something)) {
@property --bg-color {
syntax: "<color>";
inherits: false;
initial-value: #3498db;
}
.box {
background: linear-gradient(135deg, var(--bg-color), #2ecc71);
transition: --bg-color 0.8s ease;
}
.box:hover {
--bg-color: #e74c3c;
}
}非対応ブラウザでは単色のtransitionでフォールバックしつつ、対応ブラウザではグラデーションのアニメーションを楽しめるようにしています。
ただし、@supportsで@propertyを直接検出する標準的な方法はまだ確立されていません。上記のpaint()を使った判定はCSS Houdiniのサポート状況をおおまかにチェックするものです。より確実にやるなら、JavaScriptのCSS.registerPropertyの存在チェックと組み合わせるのも手ですね。
if (CSS.registerProperty) {
document.documentElement.classList.add('supports-at-property');
}/* JSで付与したクラスを使ったフォールバック */
.supports-at-property .box {
background: linear-gradient(135deg, var(--bg-color), #2ecc71);
transition: --bg-color 0.8s ease;
}まとめ
CSS @propertyを使うことで、今まで不可能だったカスタムプロパティのアニメーションができるようになりました。特にグラデーションのアニメーションや数値のカウントアップなど、以前はJavaScriptが必要だった表現がCSSだけで実現できるのは嬉しいですね。
- CSS変数は型情報がないのでそのままではアニメーションできない
@propertyでsyntax、inherits、initial-valueを定義すると補間が可能になる<color>、<angle>、<integer>など様々な型が使える- 主要ブラウザは対応済みだが、フォールバックも用意しておくと安心
今回は以上です!