Skip to content

Commit a5cd596

Browse files
andruudtabatkins
authored andcommitted
[css-properties-values-api] Add @Property. (w3c#847)
* [css-properties-values-api] Add @Property. This adds basic support for @Property, without solving any of the potentially complicated issues, like w3c#845 and w3c#846. Resolves w3c#137, at least partially. * Remove merge conflict things. * Rewrapping, tiny wording tweaks, IDL/linking fixes
1 parent fefa47f commit a5cd596

File tree

1 file changed

+213
-22
lines changed

1 file changed

+213
-22
lines changed

css-properties-values-api/Overview.bs

Lines changed: 213 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -850,37 +850,228 @@ CSSOM {#cssom}
850850
return the result.
851851
</div>
852852

853+
The <dfn>@property</dfn> rule {#at-property-rule}
854+
=================================================
855+
856+
The ''@property'' rule provides an alternative way to register a custom property,
857+
directly in a stylesheet
858+
without having to run any JS.
859+
Valid ''@property'' rules result in a [=register a custom property|registered custom property=],
860+
as if {{registerProperty()}} had been called with equivalent parameters.
861+
862+
The semantics of registered properties are the same
863+
regardless of the mechanism used to perform the registration.
864+
This means that, once registered,
865+
it does not matter whether the registration originated from {{registerProperty()}} or ''@property'':
866+
the property has the same behavior either way.
867+
868+
The syntax of ''@property'' is:
869+
870+
<pre class="prod def" nohighlight>
871+
@property <<custom-property-name>> {
872+
<<declaration-list>>
873+
}
874+
</pre>
875+
876+
''@property'' rules require a 'syntax' and 'inherits' descriptor;
877+
if either are missing,
878+
the entire rule is invalid and must be ignored.
879+
The 'initial-value' descriptor is optional
880+
only if the syntax is the [=universal syntax descriptor=],
881+
otherwise the descriptor is required;
882+
if it's missing, the entire rule is invalid and must be ignored.
883+
884+
If an ''@property'' rule contains any unknown descriptors,
885+
the entire rule is invalid and must be ignored.
886+
887+
Issue(845): What happens when we have both an ''@property'' rule, and a
888+
{{registerProperty()}} call for the same property?
889+
890+
Issue(846): What happens when ''@property'' appears inside a shadow tree?
891+
892+
893+
The 'syntax' descriptor {#the-syntax-descriptor}
894+
------------------------------------------------
895+
896+
<pre class='descdef'>
897+
Name: syntax
898+
Value: <<string>>
899+
For: @property
900+
Initial: n/a (see prose)
901+
</pre>
902+
903+
Specifies the syntax of the custom property,
904+
in the form defined by [[#syntax-strings]].
905+
This descriptor is equivalent to the {{PropertyDescriptor/syntax|syntax}} member of {{PropertyDescriptor}}.
906+
907+
The 'syntax' descriptor is required for the ''@property'' rule to be valid;
908+
if it's missing, the ''@property'' rule is invalid.
909+
910+
If the provided string does not successfully [=consume a syntax definition|parse as a syntax definition=],
911+
the descriptor is invalid and must be ignored.
912+
913+
914+
The 'inherits' descriptor {#inherits-descriptor}
915+
------------------------------------------------
916+
917+
<pre class='descdef'>
918+
Name: inherits
919+
Value: true | false
920+
For: @property
921+
Initial: n/a (see prose)
922+
</pre>
923+
924+
Specifies whether or not the custom property inherits.
925+
This is equivalent to the {{PropertyDescriptor/inherits}} member of {{PropertyDescriptor}}.
926+
927+
The inherits descriptor is required for the ''@property'' rule to be valid;
928+
if it's missing, the ''@property'' rule is invalid.
929+
930+
931+
The 'initial-value' descriptor {#initial-value-descriptor}
932+
----------------------------------------------------------
933+
934+
<pre class='descdef'>
935+
Name: initial-value
936+
Value: <<declaration-value>>
937+
For: @property
938+
Initial: the [=guaranteed-invalid value=] (but see prose)
939+
</pre>
940+
941+
Specifies the [=initial value=] of the custom property.
942+
This is equivalent to the {{PropertyDescriptor/initialValue}} member of {{PropertyDescriptor}}.
943+
944+
If the value of the 'syntax' descriptor is the [=universal syntax descriptor=],
945+
then the 'initial-value' descriptor is optional.
946+
If omitted, the initial value of the property is the [=guaranteed-invalid value=].
947+
948+
Otherwise,
949+
if the value of the 'syntax' descriptor is not the [=universal syntax descriptor=],
950+
the following conditions must be met for the the ''@property'' rule to be valid:
951+
952+
* The 'initial-value' descriptor must be present.
953+
* The 'initial-value' descriptor's value must [=consume a syntax definition|parse successfully=]
954+
according to the grammar specified by the [=syntax definition=].
955+
* The 'initial-value' must be [=computationally independent=].
956+
957+
If the above conditions are not met, the ''@property'' rule is invalid.
958+
959+
960+
Extensions to the {{CSSRule}} interface {#extensions-to-css-rule-interface}
961+
------------------------------------------------------------------------------------
962+
963+
The {{CSSRule}} interface is extended as follows:
964+
965+
<pre class='idl'>
966+
partial interface CSSRule {
967+
const unsigned short PROPERTY_RULE = 18;
968+
};
969+
</pre>
970+
971+
The <dfn interface>CSSPropertyRule</dfn> interface {#the-css-property-rule-interface}
972+
-----------------------------------------------------------------------------
973+
974+
The {{CSSPropertyRule}} interface represents an ''@property'' rule.
975+
976+
<pre class='idl' export>
977+
[Exposed=Window]
978+
interface CSSPropertyRule : CSSRule {
979+
readonly attribute CSSOMString name;
980+
readonly attribute CSSOMString syntax;
981+
readonly attribute boolean inherits;
982+
readonly attribute CSSOMString? initialValue;
983+
};
984+
</pre>
985+
986+
<dl dfn-for=CSSPropertyRule dfn-type=attribute>
987+
<dt><dfn>name</dfn>
988+
<dd>
989+
The custom property name associated with the ''@property'' rule.
990+
991+
<dt><dfn>syntax</dfn>
992+
<dd>
993+
The syntax associated with the ''@property'', exactly as specified.
994+
995+
<dt><dfn>inherits</dfn>
996+
<dd>
997+
The inherits descriptor associated withthe ''@property'' rule.
998+
999+
<dt><dfn>initialValue</dfn>
1000+
<dd>
1001+
The initial value associated with the ''@property'' rule,
1002+
which may not be present.
1003+
</dl>
1004+
8531005

8541006
Examples {#examples}
8551007
====================
8561008

8571009
Example 1: Using custom properties to add animation behavior {#example-1}
8581010
-------------------------------------------------------------------------
8591011

860-
<pre class='lang-markup'>
861-
&lt;script>
862-
CSS.registerProperty({
863-
name: "--stop-color",
864-
syntax: "&lt;color>",
865-
inherits: false,
866-
initialValue: "rgba(0,0,0,0)"
867-
});
868-
&lt;/script>
869-
870-
&lt;style>
871-
872-
.button {
873-
--stop-color: red;
874-
background: linear-gradient(var(--stop-color), black);
875-
transition: --stop-color 1s;
876-
}
877-
878-
.button:hover {
879-
--stop-color: green;
880-
}
1012+
<xmp class='lang-markup'>
1013+
<script>
1014+
CSS.registerProperty({
1015+
name: "--stop-color",
1016+
syntax: "<color>",
1017+
inherits: false,
1018+
initialValue: "rgba(0,0,0,0)"
1019+
});
1020+
</script>
8811021

882-
&lt;/style>
1022+
<style>
1023+
.button {
1024+
--stop-color: red;
1025+
background: linear-gradient(var(--stop-color), black);
1026+
transition: --stop-color 1s;
1027+
}
8831028

1029+
.button:hover {
1030+
--stop-color: green;
1031+
}
1032+
</style>
1033+
</xmp>
1034+
1035+
Example 2: Using ''@property'' to register a property {#example-2}
1036+
------------------------------------------------------------------
1037+
<xmp class='lang-markup'>
1038+
<script>
1039+
CSS.paintWorklet.addModule('circle.js');
1040+
</script>
1041+
<style>
1042+
@property --radius {
1043+
syntax: "<length>";
1044+
inherits: false;
1045+
initial-value: 0px;
1046+
}
1047+
1048+
div {
1049+
width: 100px;
1050+
height: 100px;
1051+
--radius: 10px;
1052+
background: paint(circle);
1053+
transition: --radius 1s;
1054+
}
1055+
1056+
div:hover {
1057+
--radius: 50px;
1058+
}
1059+
</style>
1060+
<div></div>
1061+
</xmp>
1062+
1063+
<pre class='lang-javascript'>
1064+
// circle.js
1065+
registerPaint('circle', class {
1066+
static get inputProperties() { return ['--radius']; }
1067+
paint(ctx, geom, properties) {
1068+
let radius = properties.get('--radius').value;
1069+
ctx.fillStyle = 'black';
1070+
ctx.beginPath();
1071+
ctx.arc(geom.width / 2, geom.height / 2, radius, 0, 2 * Math.PI);
1072+
ctx.fill();
1073+
}
1074+
});
8841075
</pre>
8851076

8861077
Security Considerations {#security-considerations}

0 commit comments

Comments
 (0)