はじめに
この記事では@property
を用いたアニメーションの作り方を紹介します。これを利用することで、JavaScriptを用いて構築せざるを得なかった多くのアニメーションをCSSだけで構築できます。
2023年7月7日現在can i useによると、@property
はすべてのモダンブラウザで対応されていません。
JavaScriptでは以下のようにして対応の可否を確認できます。
typeof window.CSS.registerProperty !== 'undefined'
@propery
はプロパティではなくルールであるため、CSSを用いた判定は少し大変です。
web.devの@property
の記事によれば以下のようにして判定を行います。
/* Check for Houdini support & register property */
@supports (background: paint(something)) {
@property --gradPoint {
syntax: '<percentage>';
inherits: false;
initial-value: 40%;
}
}
@property
を直接的に検査するのではなく、paint
ワークレットを用いて擬似的に検査しています。
この機能を用いてアニメーションを作る場合は、@property
が実装されていないブラウザで得られる情報に差が生まないような実装にしてください(アニメーションから得られる体験は除きます)。
@property
とは
@property
はCSSのアットルールの1つです。アットルールはCSSの動作を規定するCSSの記法の1つで、@keyfrmames
や@import
などが有名です。
@property
はCSS変数(CSSカスタムプロパティとも呼ばれますが、この記事ではCSS変数と呼びます)を型のチェックなどの強い制約を課して定義します。
具体的には型と初期値の設定、値の継承についての定義を行います。
@property --chart-percentage {
syntax: '<percentage>';
inherits: false;
initial-value: 30%;
}
@property
の後ろに変数名、syntax
でその型、inherits
で継承の有無、initial-value
で初期値を定義します。
syntax
に与えられる型は14個あります。主観ですがよく使われる型を紹介します。
-
'<length>'
:1px
や1rem
などwidth
プロパティに渡すような値 -
'<number>'
: 整数や少数 -
'<percentage>'
: 整数や少数の末尾に%がついた値 -
'<color>'
: カラーコードとして取り得る値 -
'<integer>'
: 整数 -
'<angle>'
:30deg
や3.14rad
のような角度を表す値
このように定義した型に違反する値でCSS変数を上書きを試みても、更新されずに元の値を持つCSS変数として扱われます。
inherits
はtrue
とfalse
で継承の有無を指定します。
initial-value
はCSS変数の初期値を定義します。syntax
で定義した型通りに値を渡す必要があり、一部の初期値を持つ型は省略可能です。
このように@property
によって定義されたCSS変数は通常のCSS変数が持たない1つの特徴を持ちます。それはトランジションで変化させることが可能ということです。単純なCSS変数とは異なり、@property
で定義された変数はこのような機能を持つので議題となっているアニメーションで活用できると言う訳です(@property
についての説明で本題を忘れそうでしたね)。
このCSSのルールはJavaScriptからも定義できます。ブラウザに定義されたwindow
のCSS
インターフェイスが持つregisterProperty
メソッドです。
記法は@property
とほとんど同じです。
window.CSS.registerProperty({
name: "--chart-percentage",
syntax: "<percentage>",
inherits: false,
initialValue: "30%",
});
CSS変数名の定義がname
で行われること以外は同じように情報を定義します。JavaScriptから定義したい場合はこちらを利用してください。
アニメーションを作る
こちらのHTML/CSSによって作られたチャートに@property
によって定義されたCSS変数を用いたアニメーションを付与していきます。
See the Pen normal-chart by KokiSakano (@kokisakano) on CodePen.
ここでは徐々に青の領域が増えていくようなアニメーションを作ります。青の領域は`conic-gradient`で指定する%の値に依存して変化します(90%の部分です)。そのためその領域をCSS変数化して0%から徐々に増やしていく方針で実装します。まずは@property
で変数の定義を行います。
@supports (background: paint(something)) {
@property --chart-percentage {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
}
型は'<percentage>'
に、継承は考慮したくないのでfalse
、初期値は0%
にしました。
次に、このCSS変数を利用してチャートを表示させます。
.main {
--chart-percentage: 90%;
background: conic-gradient(blue 0% var(--chart-percentage), gray var(--chart-percentage) 100%);
}
conic-gradient
の90%
をvar(--chart-percentage)
に置き換えて、--chart-percentage
の値も90%に更新させました。
ここまでの変更は見た目も動作も全く変化がありませんでした。最後にアニメーションを付与します。
先に、キーフレームを定義します。@property
で定義されたCSS変数ではないとトランジションできないので@supports
内に書きます。ここでは同じ場所で定義しますが、@property
で変数を定義する時に変化後の値を指定できない場合などでは別の箇所で定義して問題ないです。
@supports (background: paint(something)) {
@property --chart-percentage {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
@keyframes chart-percentage {
from {
--chart-percentage: 0%;
}
to {
--chart-percentage: 90%;
}
}
}
0%から90%まで変化させるキーフレームが定義できました。キーフレームが準備で来たのでanimation
を定義します。
.main {
--chart-percentage: 90%;
animation: chart-percentage 0.5s;
background: conic-gradient(blue 0% var(--chart-percentage), gray var(--chart-percentage) 100%);
}
キーフレームで定義した変化を0.5秒かけて行うようにしました。キーフレームは@property
を使える時でしか利用できないようにしたので、非対応のブラウザではアニメーションが無効となり、アニメーションなしのチャートが表示されます。キーフレームを@supports (background: paint(something))
外で行うと非対応のブラウザの表示に問題が発生するので注意してください。
ここまでの変更を加えるとチャートは以下のようになります。
See the Pen animation-chart by KokiSakano (@kokisakano) on CodePen.
このように@property
を用いて定義したCSS変数を用いてその変化をキーフレームで表現できればアニメーションを簡単に作れます。これまでCSSだけでは定義できなかったさまざまなアニメーションをこれを用いることで表現できるのでとても便利です。
See the Pen animation-chart by KokiSakano (@kokisakano) on CodePen.
See the Pen animation-counter by KokiSakano (@kokisakano) on CodePen.