CSS - @property
概要
ルール名 | @property |
---|---|
構文 | @property --name {syntax: " type"; inherits: bool; initial-value: value; } |
サポート | https://caniuse.com/mdn-css_at-rules_property |
CSS のカスタムプロパティ(--変数) の利用に制約を加えることにより、コードの安全性を高めるものです。2020年の Chrome 85 や 2023年の Firefox 128 でサポートされました。
説明
CSS では下記の様に変数(カスタムプロパティ)を定義・使用することができます。
:root { --text-color: #333; } body { color: var(--text-color); }
@property
を用いて上記を書き換えると次のようになります。
@property --text-color { syntax: "<color>"; inherits: false; initial-value: #333; } body { color: var(--text-color); }
@property
を用いることにより次のようなメリットがあります。
- 変数の型や仕様が明確になる。
- ルートで定義した値が不用意に上書きされなくなる。
- 変数を使用したアニメーションが改善できる。
ただし、色々な注意点も多いので、利用する際には後述の「注意点」を参照してください。
詳細
プロパティ定義(@property)
プロパティを下記の様に定義します。
@property --text-color { syntax: "<color>"; inherits: false; initial-value: #333; }
syntax
と inherits
は省略できません。initial-value
は syntax
が "*"
の時は 省略できますが、それ以外の時は省略できません。省略すると @property
定義自体が無効となります。
名前(--variable-name
)
変数名を定義します。変数名は今後の CSS の拡張とバッティングしないように --
で始める必要があります。
@property --text-color { syntax: "<color>"; inherits: false; initial-value: #333; }
シンタックス(syntax)
syntax
は変数に格納できる値の型を制限します。
@property --text-color { syntax: "<color>"; inherits: false; initial-value: #333; }
型名
型には下記の型名や auto
などのキーワードを指定します。
<number>
: 数値(例: 2.5)<integer>
: 整数(例: 123)<length>
: 長さ(例: 24px)<percentage>
: パーセンテージ(例: 25%)<length-percentage>
: 長さ又はパーセンテージ (例: 25px や 50%)<string>
: 文字列(例: "abc" や 'abc')<color>
: 色名(例: #fcc)<image>
: イメージ(例: linear-gradient(to bottom, red, blue))<url>
: URL(例: url(https://....))<angle>
: 角度(例: 45deg)<time>
: 時間(例: .2s)<resolution>
: 解像度(例: 600dpi)<transform-function>
: トランスフォーム関数(例: translateY(10px))<custom-ident>
:auto
などのキーワードや--
で始まる名前(例: --default-padding)
スペース区切りの複数指定(+)
型に +
をつけるとスペース区切りの複数個の値が指定可能となります。
@property --my-padding { syntax: "<length>+"; inherits: false; initial-value: 8px 16px; }
カンマ区切りの複数指定(#)
型に #
をつけるとカンマ区切りの複数個の値が指定可能となります。
@property --my-color { syntax: "<number>#"; inherits: false; initial-value: 255, 128, 128; }
もしくは(|)
A |
B は A または B を意味します。
@property --my-width { syntax: "<length> | <percentage>"; inherits: false; initial-value: 50vw; }
@property --my-color { syntax: "red | green | blue"; inherits: false; initial-value: red; }
全称構文定義(*)
*
はすべての型を受け付けます。
@property --my-border { syntax: "*"; inherits: false; initial-value: 1px solid gray; }
型定義に合致しない場合
initial-value
に指定した値が syntax
に違反する場合、@property
定義自体が無効となります。つまり、syntax で宣言した型宣言も無効となります。
@property --my-name { syntax: "<color>"; /* 型宣言も無効となる */ inherits: false; initial-value: 24px; /* 型宣言と合致していない */ }
上記以外の場所で型宣言に違反する値を代入しようとすると代入が無効となり、initial-value
で宣言した値や、継承可能な場合は先祖要素で正常に代入された値が参照されます。
@property --my-name { syntax: "<color>"; inherits: false; initial-value: red; } .test { --my-name: 24px; /* 型宣言に合致しない無効な値 */ font-size: var(--my-name); /* red と解釈される */ }
継承(inherits)
inherits
は祖先要素で上書きした値が子孫要素に継承されるか否かを指定します。継承不可(false
) にしておくことで、祖先コンポーネントで値が上書きされたとしても、@property
で定義した値を確実に参照できるようになります。
@property --text-color { syntax: "<color>"; inherits: true; initial-value: red; /* 初期値 */ } .parent { --text-color: blue; /* 祖先要素で上書き */ .child { color: var(--text-color); /* 継承可(true)であればblue、継承不可(false)であればred */ } }
初期値(initial-value)
初期値を指定します。
@property --text-color { syntax: "<color>"; inherits: false; initial-value: red; }
inherits
は syntax
が "*"
の時は省略可能ですが、それ以外の場合は省略できません。省略すると @property
定義自体が無効となり、型宣言も無効となります。
@property --my-name { syntax: "<color>"; inherits: false; /* initial-value を省略 */ } .parent { --my-name: 24pt; /* 型宣言も無効なので24ptも代入できてしまう */ font-size: var(--my-name); }
変数を用いたアニメーションの改善
下記は変数を用いたアニメーションの例です。赤から白にグラデーションした背景画像を、3秒かけて白から赤のグラデーションにアニメーションするものですが、色が徐々に変化するのではなく、瞬時に切り替わってしまいます。
<style> @keyframes my-animation { 0% { --start: red; --end: white; } 100% { --start: white; --end: red; } } .gradient { width: 300px; height: 50px; animation: my-animation 3s infinite alternate; background-image: linear-gradient(to right, var(--start), var(--end)); } </style> <div class="gradient"></div>
これは、CSS が red
や white
といったキーワードを色名として認識することができず、文字列と解釈してしまうことが原因です。下記の宣言を追加して --start
や --end
が色名であることを宣言することで、変数を用いたグラデーションアニメーションが期待通りに動くようになります。
@property --start { syntax: "<color>"; inherits: false; initial-value: red; } @property --end { syntax: "<color>"; inherits: false; initial-value: white; }
注意点
syntax, inherits, initial-value は省略できない
syntax
が "*"
の時に initial-value
を省略できる以外には、syntax
, inherits
, initial-value
は省略することができません。省略すると @property
定義自体が無効となってしまいます。
@property --my-color {
syntax: "<color>
inherits: false;
/* initial-value を省略してしまったので @propety 自体が無効 */
}
auto などのキーワードには <custom-indent> 型を指定する
auto
や bold
などのキーワードは <custom-ident>
型で指定します。
@property --my-font-weight { syntax: "<custom-ident>"; inherits: false; initial-value: bold; }
型を複数指定できない
syntax
には +
や #
による複数繰り返し以外には、型を複数指定することができないようです。例えば下記のような記述はできません。
@property --my-padding { syntax: "<length> <length>"; inherits: false; initial-value: 8px 16px; }
独立計算可能な初期値しか設定できない
initial-value
には独立計算可能な値しか設定することができません。例えば、24px
などの値は独立計算可能ですが、1em
などの値は親要素のフォントサイズに依存しており独立計算できないため設定が無効となり、@property
定義自体が無効となります。
@property --font-size {
syntax: "<length>";
inherits: false;
initial-value: 3em; /* 独立計算できないので無効 */
}
誤っていてもエラーが出る訳ではない
@property
の書き方を誤っていたり、syntax
で定義した型以外の値を設定したとしてもどこかにエラーメッセージが表示される訳ではありません。開発者ツールの [Elements] で表示される @property
一覧で確認するなど、正常に設定されているかを確認する必要があります。
@property --font-size {
syntax: "<length>";
inherits: false;
initial-value: 3em; /* ← 誤って設定していてもエラーメッセージは無い */
}
<length-percentage> と <length> | <percentage> は違う
<length-percentage>
と <length> | <percentage>
は多少異なります。前者は長さとパーセンテージの混在が許されますが、後者は混在が許されません。
@property --my-size-1 { syntax: "<length-percentage>+"; inherits: false; initial-value: 100% 100px; /* 混在が許される */ } @property --my-size-2 { syntax: "<length>+ | <percentage>+"; inherits: false; initial-value: 100% 100px; /* 混在は許されない */ }
下記も同様に混在とみなされます。
@property --my-size-1 { syntax: "<length-percentage>"; inherits: false; initial-value: calc(100% - 100px); /* 混在が許される */ } @property --my-size-2 { syntax: "<length> | <percentage>"; inherits: false; initial-value: calc(100% - 100px); /* 混在は許されない */ }
初期値に initial や inherit などは使用できない
initial-value
に initial
, inherit
, unset
, revert
, rever-layer
の値を設定することはできません。設定すると @property
定義自体が無効となります。
@property --my-name {
syntax: "*";
inherits: false;
initial-value: initial; /* 設定できない */
}
仕様への要望
使用してみての感想ですが、次のような強化があればな...と思います。
inherits
や initial-value
は省略できるようにして欲しい。
@property --my-color { syntax: "<color>"; /* inherits省略 */ /* initial-value省略 */ }
下記のようなシンタックスもサポートしてほしい。
syntax: "<length> <length>"; syntax: "<length>{1,4}"; syntax: "[<length> | <percentage>]#";
auto
や solid
などのキーワードも --my-name
などのカスタムプロパティも型には <custom-ident>
を指定しますが、<keyword>
と <custom-ident>
に分けてほしい。
@property --default-border { syntax: "<length> <keyword> <color>"; inherits: false; initial-value: 1px solid gray; }
あとは、開発者ツールのコンソールでエラー表示したり、Nu Html Checker などのバリデーションツールでエラー検出して欲しいですね。
リンク
- https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule
- https://developer.mozilla.org/ja/docs/Web/CSS/@property
- https://caniuse.com/?search=%40property