1. はじめに
CSSは、ウェブドキュメントのレイアウト、描画、または動作を変更するために操作できる包括的なプロパティセットを定義しています。しかし、ウェブ著者はこのセットを追加のプロパティで拡張したい場合がよくあります。
[css-variables]は、 ユーザーが制御できるプロパティを定義するための基本的な手段を提供しますが、これらのプロパティは常にトークンリストとして値を取り、必ず継承され、 他のプロパティの値にvar()参照を使って再組み込みされることでのみドキュメントのレイアウトや描画に影響を与えることができます。
この仕様は[css-variables]を拡張し、 型、初期値、継承動作を持つプロパティの登録を可能にします。 これは二つの方法で行えます:
-
JS APIである
registerProperty()
メソッド -
CSSのat規則である@property規則
この仕様は[css-paint-api-1]や[css-layout-api-1]とも補完関係にあり、 これらはカスタムプロパティが描画やレイアウト動作に直接影響を与えることを可能にします。
2. 登録されたカスタムプロパティ
カスタムプロパティは登録されたカスタムプロパティになることができ、
UAが定義したプロパティのように振る舞います。
UAによって構文チェックされるシンタックス、初期値、特定の継承動作を持つことになります。
これは@property規則や
registerProperty()
JS関数によって行えます。
カスタムプロパティは、Document
に対して、
その名前の有効な@property規則がドキュメントのいずれかのスタイルシートに定義されているか、
またはその名前がドキュメントの[[registeredPropertySet]]
スロットに含まれていれば登録されているとみなされます
(つまり、registerProperty()
が呼び出されて登録された場合です)。
登録されたカスタムプロパティは未登録の カスタムプロパティと同様に動作しますが、 以下に定義する点が異なります。
2.1. 登録の判定
登録されたカスタムプロパティはカスタムプロパティ登録を持ち、 それを本物のプロパティのように扱うために必要な全データを含みます。 これは構造体であり、以下から成ります:
-
プロパティ名(カスタムプロパティ名文字列)
-
構文(構文文字列)
-
inheritフラグ(boolean)
もしDocument
の
[[registeredPropertySet]]
スロットがそのカスタムプロパティ名を持つレコードを含んでいれば、
登録はそのレコードとなります。
そうでない場合、
Document
の
アクティブなスタイルシートにそのカスタムプロパティ名を持つ有効な
@property規則が一つ以上あれば、
文書順で最後のものがその登録となります。
それ以外の場合は登録がなく、 カスタムプロパティは登録されたカスタムプロパティではありません。
2.2. 構文解析時の挙動
登録されたカスタムプロパティは未登録の カスタムプロパティと全く同じようにパースされます; ほぼ何でも許可されます。 プロパティの登録された構文は構文解析時にはチェックされません。
注: ただし、 構文は算出値時にチェックされ、 var()による代入の前に検証されます。 §2.4 算出値時の挙動を参照してください。
なぜカスタムプロパティは構文チェックされないのか?
ページのCSSをパースする際、 UAは速度やメモリのために様々な最適化を行います。
その最適化の一つは、実際に効果があるプロパティのみを保存することです; 無効なプロパティは破棄され、 同じ宣言ブロック内で複数回同じプロパティが書かれても、 最後の有効なもの以外はすべて破棄されます。 (これはCSSのエラー回復と将来互換性の重要な部分です。)
この動作は、プロパティの構文がページの生存期間中に変化しない場合は問題ありません。 しかし、カスタムプロパティが登録されると構文が変化する可能性があり、 以前は無効だったプロパティが突然有効になることがあります。
これに対応する方法は、最初は無効だった宣言もすべて保存する(ページのメモリコスト増加)か、 新しい構文ルールでページ全体のCSSを再パースする(カスタムプロパティ登録時の処理コスト増加)しかありません。 どちらも望ましくありません。
さらに、 UA定義プロパティの構文はユーザーが見ているUAのバージョンで決まり、 これはページ著者の制御外です。 これこそがCSSのエラー回復動作や複数宣言を書く慣習の理由です。 一方、カスタムプロパティはページ著者が制御でき、 任意のスタイルシートやスクリプトによって構文が決まります; 不確実性がありません。 構文違反のカスタムプロパティを破棄するのは著者の便宜のためだけであり、 UA定義プロパティの場合の必然性はありません。
2.3. 指定値時の挙動
未登録のカスタムプロパティと同様に、 登録されたカスタムプロパティは登録された構文に関わらず、 CSS全体キーワード(inheritやrevertなど)を受け入れます。 その動作はCSS Cascading 4 §7.3 明示的なデフォルト化で定義されています。
2.4. 算出値時の挙動
算出値は登録されたカスタムプロパティの 登録の構文によって決まります。
もし登録の構文がユニバーサル構文定義であれば、 算出値は未登録のカスタムプロパティと同じになります(変数代入後の指定値、または保証された無効値)。
それ以外の場合は、プロパティの値を登録された構文に従ってパースを試みます。 失敗した場合、その宣言は算出値時に無効となり、 算出値はそれに応じて決定されます。 成功した場合は、構文の詳細により算出値が決まります:
"<length>"
, "<length-percentage>"
, "<angle>"
,
"<time>"
, "<resolution>"
, "<integer>"
,
"<number>"
,
"<percentage>"
値の場合:
-
指定値がその他の数値リテラル (例:5や20%)なら、 算出値はそのままです。 (特に、パーセンテージは何にも解決されません。)
-
指定値がそれら型の値になる関数 (例:数式関数)なら、 算出値はその関数によって定義されます。
"<color>"
値の場合、
値は色値の解決によって算出されます。
CSS Color 4 §14.
色値の解決参照。
"<custom-ident>"
やident、"*"
値の場合、
算出値は指定値のままです。
"<url>"
値の場合、
算出値は以下のいずれかになります:
-
URLが相対URLなら、 算出値は[css3-values]で説明される絶対URLに解決されます。
-
それ以外の場合は指定値のままです。
URL挙動の例
例えば、--url-fooと--url-barが<url>構文で登録された
カスタムプロパティで、スタイルシートが/style/foo/foo.css
にあるとします:
div{ --url-foo : url ( "foo.png" ); }
そしてもう一つ、/style/bar/bar.css
にあるスタイルシート:
div{ --url-bar : url ( "bar.png" ); }
最後に/index.html
というドキュメント:
< link href = "/style/foo/foo.css" rel = "stylesheet" type = "text/css" > < link href = "/style/bar/bar.css" rel = "stylesheet" type = "text/css" > < div style = "background-image: var(--url-foo), var(---url-bar);" > </ div >
この場合、var(--url-foo)参照は/style/foo
に対してURLを解決し、
var(--url-bar)参照は/style/bar
に対して解決します。
一方、
--url-fooと--url-barが未登録の場合は、
リテラル値(相対URL)を/index.html
のスタイルシートに代入し、
そのURLは/index.html
に対して解決されます。
"<image>"
値の場合、
算出値はcomputed <image>となります。
"<transform-function>"
や"<transform-list>"
値の場合、
算出値は全ての長さが算出値に解決された上で指定値のままです。
乗算子付きの構文の場合、 算出値は基底型の算出値リストとなります。
|コンビネータで指定された構文の場合、 算出値は値が一致する最初の句の算出値ルールを適用して決定されます。
2.5. アニメーション動作
注: [css3-animations]および[css3-transitions]により、 カスタムプロパティを参照するアニメーションやトランジションを指定することが可能です。
アニメーションやトランジションで参照された場合、 カスタムプロパティの値は、パースされた型に従い補間され、算出値によって処理されます。
注:
これは、<color>+
や<color>#
のような値リストは単純なリストとして補間され、
各コンポーネントがインデックスごとに対応し、コンポーネント数が一致しない場合は失敗することを意味します。
上記のルールの例外として、
<transform-list>
、
<transform-function>
、
または<transform-function>+
としてパースされた値は、transformプロパティに準じて補間されます。
注:
何らかの理由で、カスタムプロパティが<transform-function>#
構文で定義されている場合、
まず単純なリストとして補間され、その後各リスト項目がtransform値として補間されます。
注: カスタムプロパティの登録(または登録変更)は算出値を変更でき、 これがCSSトランジションを開始または中断する場合があります。
2.6. 条件付き規則
§2.2 構文解析時の挙動で述べたように、 未登録・登録済み両方のカスタムプロパティは、 構文解析時に(ほぼ)すべての値を受け入れます。 登録済み カスタムプロパティは、算出値時のみ構文を適用します。
したがって、カスタムプロパティは、 登録済みか未登録かに関わらず、 @supports規則の中で「true」と判定されます。 (非常に寛容な)カスタムプロパティの汎用構文に違反しない限りです。
syntax : "<color>" ;
で登録されていても、
@supports (--foo: 1em) {...}
のような規則は依然としてtrueと判定され、スタイルが適用されます。
なぜなら宣言が有効なプロパティとして正常にパースされるからです。
2.7. var()による代入
未登録のカスタムプロパティと同様に、 登録済みカスタムプロパティの値もvar()関数で他の値に代入できます。 ただし、登録済みカスタムプロパティは元のトークン列ではなく、 算出値として代入されます。
登録済みカスタムプロパティを参照するvar()関数は、 同等のトークン列に置き換えられなければなりません。 これは、算出値を直列化し、 その文字列をトークン化した際に得られるトークン列と同等です。
div{ font-size : 10 px ; --x : 8 em ; --y : var ( --x); }
--xの算出値(直列化時)が "80px" となるため、 --yの算出値は値 "80"、単位 "px" を持つ<dimension-token>となります。
2.7.1. var()参照のフォールバック
var()関数で登録済みカスタムプロパティを参照する場合、 フォールバック値を指定できます。 ただしフォールバック値は参照先カスタムプロパティの構文定義に一致していなければならず、 一致しない場合はその宣言は算出値時に無効となります。
注: このルールはフォールバックが実際に使われるかどうかに関わらず適用されます。
2.7.2. 相対単位による依存サイクル
登録済みカスタムプロパティは未登録のカスタムプロパティと同じ依存サイクル解決規則に従いますが、 以下の追加制約があります:
次の構文要素を持つ登録済みカスタムプロパティについて: <length> または <length-percentage>:
-
プロパティに以下の単位が含まれる場合:em、ex、cap、ch、ic、lh; この場合、プロパティと現在の要素のfont-size間にエッジを追加します。
-
プロパティにlh単位が含まれる場合、 プロパティと現在の要素のline-height間にエッジを追加します。
-
プロパティに以下の単位が含まれる場合:rem、rlh; この場合、プロパティとルート要素のfont-size間にエッジを追加します。
-
プロパティにrlh単位が含まれる場合、 プロパティとルート要素のline-height間にエッジを追加します。
CSS. registerProperty({ name: "--my-font-size" , syntax: "<length>" , initialValue: "0px" , inherits: false });
次の場合、依存サイクルが発生します:
div{ --my-font-size : 10 em ; font-size : var ( --my-font-size); }
font-sizeは、値unset が指定されたかのように振る舞います。
2.8. Shadow DOM
CSSの多くの概念と異なり
(CSS Scoping 1 §3.5
名前定義構造体と継承参照)、
プロパティ登録はツリーのスコープに限定されません。
登録は、最も外側のドキュメントでもシャドウツリー内でも、
Document
のグローバル登録マップで相互に作用します。
なぜ登録をスコープできないのか?
プロパティ登録をスコープできると便利な用途があります。たとえばShadow DOMを使ったコンポーネントが 独自内部用にカスタムプロパティを登録する場合、 外部ページにはその登録が見えない方がよいでしょう。 外部ページは、そのプロパティを使っていることすら知らないからです。
しかし、登録をスコープしない理由も存在します。カスタムプロパティはコンポーネントへ データを渡す用途にも使われるため、 外部ページがカスタムプロパティを設定し、登録による構文チェックを受けることが有用です。 また、プロパティの初期値などの概念も、 プロパティ登録がグローバルでなければ意味を持ちません。 登録がグローバルであれば、ドキュメントルートにも適用されます。
上記は登録スコープを制御可能にするべきだという理由にはなりますが、 グローバルで強制すべき理由にはなりません。
登録をグローバルにする必要があるのは、 要素が複数のツリースコープに同時に存在でき、 各ツリースコープのスタイルが混在してカスケードされるからです。 これはホスト要素にも当てはまります。 ホスト要素は外部ツリーに属しつつ、シャドウツリーの :hostセレクタでスタイル可能です。 また、シャドウDOM内の要素も外部ツリーから ::part()疑似要素でターゲット可能です。
もし登録がツリースコープごとに可能で、 同じプロパティが内外両方で登録された場合、 どちらの登録を使って値をパースすべきか不明瞭になります。 どのツリー由来かを追跡し(他のツリースコープ値で実装されているように)、 対応する登録を適用しても、 シャドウDOM側が期待する値空間と外部ツリーのカスケードによって 全く異なる値が適用されることになり、想定外の挙動となる可能性があります。
カスタムプロパティがShadow DOMコンポーネントの公開APIとして公開される場合、 このグローバル登録動作は意図通りに機能します。 外部ページが同名のカスタムプロパティを別用途で使っている場合、 それは既に解決すべき競合であり、登録動作が状況を悪化させることはありません。
コンポーネントの内部用途でのみ使うカスタムプロパティの場合は、 他のコンテキストと競合しないようなるべくユニークな名前を付けることが推奨されます。 例えばプロジェクト名や、短い乱数文字列などをプロパティ名に含めることで実現できます。
3. @property規則
@property規則は、JSを実行せずにスタイルシート内で直接
カスタムプロパティ登録
を表します。
有効な@property規則は、
登録済みカスタムプロパティとなり、
registerProperty()
が同等のパラメータで呼ばれた場合と同じ結果となります。
@propertyの構文は:
@property <custom-property-name> { <declaration-list> }
有効な@property規則は、 プロパティ名としてその規則の前置部にある<custom-property-name>を直列化したものを持つ カスタムプロパティ登録 を表します。
@property規則にはsyntaxおよびinheritsディスクリプタが必要です。 いずれかが欠けている場合、規則全体は無効となり無視されます。 initial-valueディスクリプタは 構文がユニバーサル構文定義の場合のみ省略可能であり、 それ以外は必須です。欠けている場合は規則全体が無効となり無視されます。
未知のディスクリプタは無効として無視されますが、 @property規則自体は無効になりません。
注: §2.1
登録の判定で規定されている通り、
同じ<custom-property-name>に対して
複数の有効な@property規則が定義された場合、
スタイルシート順で最後のものが「勝ち」となります。
CSS.registerProperty()
によるカスタムプロパティ登録は、同じ<custom-property-name>に対する
すべての@property規則よりも優先されます。
3.1. syntaxディスクリプタ
名前: | syntax |
---|---|
対象: | @property |
値: | <string> |
初期値: | n/a(本文参照) |
@property規則が表すカスタムプロパティ登録の構文を指定し、 プロパティ値の算出値時のパース方法を制御します。
syntaxディスクリプタは@property規則が有効であるために必須です。 欠けている場合@property規則は無効です。
指定された文字列が有効な構文文字列でない場合(構文定義の消費を行った際に失敗する場合)、 ディスクリプタは無効となり無視されます。
3.2. inheritsディスクリプタ
名前: | inherits |
---|---|
対象: | @property |
値: | true | false |
初期値: | n/a(本文参照) |
@property規則が表すカスタムプロパティ登録のinheritフラグを指定します。 これによりプロパティがデフォルトで継承されるかどうかを制御します。
inheritsディスクリプタは@property規則が有効であるために必須です。 欠けている場合@property規則は無効です。
3.3. initial-valueディスクリプタ
名前: | initial-value |
---|---|
対象: | @property |
値: | <declaration-value>? |
初期値: | 保証された無効値(ただし本文参照) |
@property規則が表すカスタムプロパティ登録の初期値を指定します。 これによりプロパティの初期値が制御されます。
syntaxディスクリプタの値がユニバーサル構文定義の場合、 initial-valueディスクリプタは省略可能です。 省略された場合、プロパティの初期値は保証された無効値になります。
それ以外の場合、 syntaxディスクリプタの値がユニバーサル構文定義でない場合、 @property規則が有効であるためには以下の条件を満たす必要があります:
-
initial-valueディスクリプタが存在すること。
-
initial-valueディスクリプタの値が、指定された構文定義に従って正常にパースされること。
-
initial-valueは計算的に独立していること。
上記条件が満たされない場合、@property規則は無効です。
4. JSによるカスタムプロパティの登録
JSでカスタムプロパティを登録するために、
CSS
オブジェクトはregisterProperty()
メソッドで拡張されます:
dictionary PropertyDefinition {required DOMString name ;DOMString syntax = "*";required boolean inherits ;DOMString initialValue ; };partial namespace CSS {undefined registerProperty (PropertyDefinition ); };
definition
さらに、Document
オブジェクトは新しい[[registeredPropertySet]]
プライベートスロットを持つようになり、
これは登録済みカスタムプロパティを記述するレコードの集合です。
4.1.
registerProperty()
関数
registerProperty(PropertyDefinition definition)
メソッドは、
definition
で指定された設定オプションに従ってカスタムプロパティを登録します。
呼び出されると、カスタムプロパティ登録アルゴリズムを実行し、
definition
引数の各オプションを同名の引数として渡します。
-
property setを現在のグローバルオブジェクトの関連付けられた
Document
の[[registeredPropertySet]]
スロットの値とする。 -
nameがカスタムプロパティ名文字列でない場合、SyntaxErrorをthrowしてこのアルゴリズムを終了する。
property setにすでにnameをプロパティ名とするエントリがある場合(コードポイント単位で比較)、InvalidModificationErrorをthrowしてこのアルゴリズムを終了する。
-
syntaxから構文定義の消費を試みる。 失敗した場合、SyntaxErrorをthrowする。 成功した場合、返された構文定義をsyntax definitionとする。
-
syntax definitionがユニバーサル構文定義であり、 initialValueが存在しない場合、 parsed initial valueを空にする。 これは[css-variables]で定義されているカスタムプロパティの「デフォルト」初期値と同一に扱う。 このアルゴリズムの次のステップに進む。
それ以外の場合、 syntax definitionがユニバーサル構文定義ならば、 initialValueを<declaration-value>としてパースする。 失敗した場合、SyntaxErrorをthrowしてこのアルゴリズムを終了する。 成功した場合パース結果をparsed initial valueとし、このアルゴリズムの次のステップへ進む。
それ以外の場合、initialValueが存在しない場合、SyntaxErrorをthrowしてこのアルゴリズムを終了する。
それ以外の場合、
initialValue
をsyntax definitionに従ってパースする。 失敗した場合、SyntaxErrorをthrowして終了する。成功した場合パース結果をparsed initial valueとし、 parsed initial valueが計算的に独立していなければ、SyntaxErrorをthrowして終了する。
-
inherit flagをinheritsの値に設定する。
-
registered propertyを構造体として作成し、 プロパティ名はname、 構文はsyntax definition、 初期値はparsed initial value、 inheritフラグはinherit flagとする。 registered propertyをproperty setに追加する。
プロパティ値が計算的に独立しているとは、 その値が要素自身のプロパティ値とCSSで変更できない「グローバル」情報のみで算出値に変換可能な場合を指します。
一方、3emは計算的に独立していません。 なぜなら要素(または親要素)のfont-size値に依存するためです。 また、var()関数を使った値も、 カスタムプロパティの値に依存するため計算的に独立ではありません。
カスタムプロパティが型付きで登録されると、 そのプロパティの指定値が算出値になる処理は選択された型によって完全に定義されます。 詳細は§2.4 算出値時の挙動を参照してください。
注: プロパティを登録解除する方法は将来追加される可能性があります。
カスタムプロパティの登録はカスケードに一切影響を与えない必要があります。 登録済みプロパティにどんな構文が指定されていても、 パース時には依然としてカスタムプロパティとして通常通りパースされ、 ほぼあらゆる値を受け入れます。 指定値が登録済み構文に違反した場合のみ、 そのプロパティは算出値時に無効となり(初期値にリセットされます)。
.thing{ --my-color : green; --my-color : url ( "not-a-color" ); color : var ( --my-color); }
「thing」クラスの要素のcolorプロパティは inheritに設定されます。 2つ目の--my-color宣言がパース時に1つ目を上書きします(両方とも有効)。 var()参照がcolorプロパティ内で算出値時に無効(url("not-a-color")が色でないため)となります。 このCSSパイプライン(算出時)では、利用可能な唯一のフォールバックはプロパティの初期値であり、 colorの場合はinheritです。 有効な値(green)が存在しても、 パース時にURLが上書きされて削除されます。
次のように呼び出した場合:
CSS. registerProperty({ name: "--my-color" , syntax: "<color>" , initialValue: "black" , inherits: false });
パース処理自体は、登録が上記スタイルシートより前でも後でも大きくは変わりません。 唯一の違いは、算出値時に--my-colorプロパティ自体が無効となり初期値のblackにリセットされることです。 その後colorは有効に blackに設定され、 算出値時に無効となってinheritになることはありません。
4.2.
PropertyDefinition
辞書
PropertyDefinition
辞書は、
著者が指定したカスタムプロパティの設定オプションを表します。PropertyDefinition
辞書には以下のメンバーが含まれます:
name
, 型: DOMString-
定義するカスタムプロパティの名前。
syntax
, 型: DOMString(デフォルトは"*"
)-
このカスタムプロパティがどのように構文解析されるかを表す文字列。
inherits
, 型: boolean-
このカスタムプロパティがDOMツリー上で継承される場合はTrue、そうでなければFalse。
initialValue
, 型: DOMString-
このカスタムプロパティの初期値。
5. 構文文字列
構文文字列は、登録済みカスタムプロパティが受け入れる値の型を記述します。構文文字列は、構文成分名からなり、 必要に応じて乗算子やコンビネータで結合されます。
構文文字列は構文定義にパース可能であり、これは以下のいずれかです:
-
構文成分のリスト。各成分は§ 5.1 サポートされる名前で指定された値型を受け入れます。
-
ユニバーサル構文定義(*)、すべての有効なトークンストリームを受け入れます。
注: 指定された構文に関係なく、すべてのカスタムプロパティはCSS全体キーワードを受け入れ、適切に処理します。
"<length>"
-
長さ値を受け入れます
"<length> | <percentage>"
-
長さ、パーセンテージ、パーセンテージのcalc式、長さのcalc式を受け入れます。ただし長さとパーセンテージの混在calc式は受け入れません。
"<length-percentage>"
-
"<length> | <percentage>"
が受け入れるすべての値に加え、長さとパーセンテージの混在calc式も受け入れます。 "big | bigger | BIGGER"
-
ident
big
、bigger
、BIGGER
のいずれかを受け入れます。 "<length>+"
-
長さ値の空白区切りリストを受け入れます。
- "*"
-
任意の有効なトークンストリームを受け入れます
注: 構文文字列の内部文法はCSS値定義構文のサブセットです。今後の仕様レベルでは、文法の複雑さが拡張され、CSSプロパティの柔軟性に近いカスタムプロパティが可能になる予定です。
この章の残りでは、構文文字列の内部文法について説明します。
5.1. サポートされる名前
このセクションでは、サポートされる構文成分名と、それによって受け入れられる型を定義します。
- "<length>"
-
有効な<length>値
- "<number>"
- "<percentage>"
-
有効な<percentage>値
- "<length-percentage>"
-
有効な<length>または<percentage>値、さらに<calc()>式で長さとパーセンテージ成分が組み合わされた値も受け入れます。
- "<color>"
-
有効な<color>値
- "<image>"
-
有効な<image>値
- "<url>"
-
有効な<url>値
- "<integer>"
-
有効な<integer>値
- "<angle>"
-
有効な<angle>値
- "<time>"
-
有効な<time>値
- "<resolution>"
-
有効な<resolution>値
- "<transform-function>"
- "<custom-ident>"
-
有効な<custom-ident>値
- 識別子として開始する任意のシーケンス(識別子の開始)、 名前として消費可能、かつ<custom-ident>生成規則に一致するもの
-
その識別子
注: <custom-ident>同士はコードポイント単位で比較されます。 これはUA定義CSSの通常の動作(ASCIIのみ、ASCII大文字小文字区別なし)とは異なります。 したがって
Red
のような識別子を指定した場合、正確な値Redのみが受け入れられ、 redやREDなど他の大文字小文字パターンは一致しません。 識別子はASCIIかつ小文字で記述することが推奨されます(CSSの慣習に合わせるため)。 - "<transform-list>"
-
有効な<transform-function>値のリスト。
"<transform-list>"
は乗算済みデータ型名であり"<transform-function>+"
と同等です。
注: "*"
という構文文字列はユニバーサル構文定義を生成し、これは構文成分ではありません。
したがって、"*"
は乗算子やコンビネータと組み合わせることはできません。
5.2. 「+」と「#」乗算子
乗算済みデータ型名を除く全ての構文成分名は、直後に乗算子を付加できます:
- U+002B PLUS SIGN (+)
-
空白区切りリストを示します。
- U+0023 NUMBER SIGN (#)
-
カンマ区切りリストを示します。
注: 乗算子は直前の構文成分名の直後に記述する必要があります。
5.3. 「|」コンビネータ
構文文字列はU+007C VERTICAL LINE (|)を使って複数の構文成分名を並べることができます。このような構文文字列は複数の構文定義を持つことになります。
複数の構文成分を持つ構文定義でCSS値を解析する際は、指定順で成分がマッチされます。
注: つまり、構文文字列"red | <color>"
では、
redは識別子としてパースされ、
blueは<color>としてパースされます。
5.4. 構文文字列の解析
5.4.1. 定義
- データ型名
-
U+003C LESS-THAN SIGN (<)で始まり、0個以上のidentコードポイントが続き、U+003E GREATER-THAN SIGN (>)で終わるコードポイントの並び。
- 乗算済みデータ型名
- 構文成分
- 構文成分名
-
コードポイントの並びであり、データ型名、 または<custom-ident>を生成できる並び。
- 構文定義
-
構文成分のリストからなるオブジェクト。
- ユニバーサル構文定義
-
すべての有効なトークンストリームを受け入れる特別な構文定義。
5.4.2. 構文定義の消費
-
stringの長さが0なら失敗を返す。
-
stringの長さが1で、 唯一のコードポイントがU+002A ASTERISK (*)なら、 ユニバーサル構文定義を返す。
-
streamを入力ストリームとしてstringのコードポイントから作成し、[css-syntax-3]に従って前処理する。 definitionは空のリストとして初期化する。
-
構文成分の消費をstreamから行う。 失敗なら失敗を返す。成功なら返された値をdefinitionに追加する。
streamから可能な限り空白を消費する。
streamの次の入力コードポイントを消費する:
- EOF
-
definitionを返す。
- U+007C VERTICAL LINE (|)
-
ステップ5を繰り返す。
- その他:
-
失敗を返す。
5.4.3. 構文成分の消費
streamから可能な限り空白を消費する。
componentを新しい構文成分(nameとmultiplierは空で初期化)として作成する。
streamから次の入力コードポイントを消費する:
- U+003C LESS-THAN SIGN (<)
-
データ型名の消費をstreamから行う。 文字列が返された場合、componentのnameにその値をセットする。 それ以外は失敗を返す。
- ident-startコードポイント
- U+005C REVERSE SOLIDUS (\)
-
ストリームがidentシーケンスで始まる場合、 現在の入力コードポイントを再消費し、 identシーケンスの消費をstreamから行い、 componentのnameにその値をセットする。 それ以外は失敗を返す。
componentのnameが<custom-ident>としてパースできない場合は失敗を返す。
- その他
-
失敗を返す。
componentのnameが乗算済みデータ型名の場合、 componentを返す。
streamの次の入力コードポイントがU+002B PLUS SIGN (+)またはU+0023 NUMBER SIGN (#)であれば、 streamから次の入力コードポイントを消費し、 componentのmultiplierに現在の入力コードポイントをセットする。
componentを返す。
5.4.4. データ型名の消費
注: このアルゴリズムはU+003C LESS-THAN SIGN (<) コードポイントがすでにストリームから消費されていることを前提とします。
nameを、U+003C LESS-THAN SIGN (<) コードポイントのみを含む文字列として初期化する。
繰り返し次の入力コードポイントを消費する:
- U+003E GREATER-THAN SIGN (>)
-
コードポイントをnameに追加する。 nameがサポートされる構文成分名であればnameを返し、 それ以外は失敗を返す。
- identコードポイント
-
コードポイントをnameに追加する。
- その他
-
失敗を返す。
6. CSSOM
[[registeredPropertySet]]
スロットを無視し、
すべてのカスタムプロパティを未登録として扱う必要があります。 6.1.
CSSPropertyRule
インターフェイス
CSSPropertyRule
インターフェイスは@property規則を表します。
[Exposed =Window ]interface CSSPropertyRule :CSSRule {readonly attribute CSSOMString name ;readonly attribute CSSOMString syntax ;readonly attribute boolean inherits ;readonly attribute CSSOMString ?initialValue ; };
name
, 型:CSSOMString、読み取り専用- @property 規則に関連付けられたカスタムプロパティ名です。
syntax
, 型:CSSOMString、読み取り専用- @property に関連付けられた構文。指定されたままの内容です。
inherits
, 型:boolean、読み取り専用- @property 規則に関連付けられた inherits 記述子です。
initialValue
, 型:CSSOMString、読み取り専用、nullable- @property 規則に関連付けられた初期値です。 存在しない場合もあります。
-
文字列
"@property"
、続いて1つのスペース (U+0020)。 -
規則のnameに対して識別子の直列化を実行した結果、続いてスペース。
-
文字列
"{ "
(左中括弧とスペース)。 -
文字列
"syntax:"
、続いてスペース。 -
文字列
"inherits:"
、続いてスペース。 -
規則のinherits属性値に応じて:
- true
-
文字列
"true"
、続いてセミコロン、スペース。 - false
-
文字列
"false"
、続いてセミコロン、スペース。
-
規則のinitial-valueが存在する場合は、以下の手順:
-
文字列
"initial-value:"
。 -
規則のinitial-valueにCSS値の直列化を実行した結果、続いてセミコロン、スペース。
-
-
右中括弧 (U+007D)。
6.2.
CSSStyleValue
具現化
指定値の場合、値から構成値リストの具現化を行い、結果を返す。
算出値の場合:
-
値が<length>, <integer>, <number>, <angle>, <time>, <resolution>, <percentage>または<length-percentage>の場合、数値値の具現化を行い、結果を返す。
-
値が<transform-function>の場合は<transform-function>の具現化を行い、結果を返す。
-
値が<transform-list>の場合は<transform-list>の具現化を行い、結果を返す。
-
値が<image>の場合はCSSImageValueとして具現化し、結果を返す。
-
syntaxがユニバーサル構文定義の場合、値から構成値リストの具現化を行い、結果を返す。
-
それ以外の場合はCSSStyleValueとして具現化し、
[[associatedProperty]]
内部スロットにpropertyをセットし、結果を返す。
7. 例
7.1. 例1: カスタムプロパティによるアニメーション動作の追加
< script > CSS. registerProperty({ name: "--stop-color" , syntax: "<color>" , inherits: false , initialValue: "rgba(0,0,0,0)" }); </ script > < style > . button { --stop-color : red ; background : linear-gradient( var ( --stop-color ), black ); transition : -- stop-color 1 s ; } . button : hover { --stop-color : green ; } </ style >
7.2. 例2: @propertyでプロパティを登録
< script > CSS. paintWorklet. addModule( 'circle.js' ); </ script > < style > @ property --radius { syntax : "<length>" ; inherits : false ; initial-value : 0px ; } div { width : 100 px ; height : 100 px ; --radius : 10 px ; background : paint ( circle ); transition : -- radius 1 s ; } div : hover { --radius : 50 px ; } </ style > < div ></ div >
// circle.js registerPaint( 'circle' , class { static get inputProperties() { return [ '--radius' ]; } paint( ctx, geom, properties) { let radius= properties. get( '--radius' ). value; ctx. fillStyle= 'black' ; ctx. beginPath(); ctx. arc( geom. width/ 2 , geom. height/ 2 , radius, 0 , 2 * Math. PI); ctx. fill(); } });
8. セキュリティに関する考慮事項
これらの機能によって新たなセキュリティ問題は現時点では知られていません。
9. プライバシーに関する考慮事項
これらの機能によって新たなプライバシー問題は現時点では知られていません。
10. 変更点
10.1. 2020年10月13日作業草案以降の変更点 Working Draft of 13 October 2020
/* 2024年3月20日まで */
-
"initial-value" を <declaration-value>? とし、カスタムプロパティと同じにした (#9078)
-
シャドウツリー内で @Property を許可 (#1085)
-
プロパティ登録がグローバルであり、シャドウスコープでない理由の説明を追加。
-
他の仕様で使えるよう "registered custom property" や "universal syntax definition" をエクスポート (#1020)
-
"guaranteed-invalid value" の代わりに "invalid at computed-value time" を使用するようにした。