diff --git a/css-properties-values-api/Overview.bs b/css-properties-values-api/Overview.bs index dc568075..f7f899b9 100644 --- a/css-properties-values-api/Overview.bs +++ b/css-properties-values-api/Overview.bs @@ -911,6 +911,158 @@ and affects how the custom property calculates its [=computed value=]. return the result. +The @property rule {#at-property-rule} +================================================= + +The ''@property'' rule provides an alternative way to register a custom property, +directly in a stylesheet +without having to run any JS. +Valid ''@property'' rules result in a [=register a custom property|registered custom property=], +as if {{registerProperty()}} had been called with equivalent parameters. + +The semantics of registered properties are the same +regardless of the mechanism used to perform the registration. +This means that, once registered, +it does not matter whether the registration originated from {{registerProperty()}} or ''@property'': +the property has the same behavior either way. + +The syntax of ''@property'' is: + +
+	@property <> {
+		<>
+	}
+	
+ +''@property'' rules require a 'syntax' and 'inherits' descriptor; +if either are missing, +the entire rule is invalid and must be ignored. +The 'initial-value' descriptor is optional +only if the syntax is the [=universal syntax descriptor=], +otherwise the descriptor is required; +if it's missing, the entire rule is invalid and must be ignored. + +If an ''@property'' rule contains any unknown descriptors, +the entire rule is invalid and must be ignored. + +Issue(845): What happens when we have both an ''@property'' rule, and a +{{registerProperty()}} call for the same property? + +Issue(846): What happens when ''@property'' appears inside a shadow tree? + + +The 'syntax' descriptor {#the-syntax-descriptor} +------------------------------------------------ + +
+	Name: syntax
+	Value: <>
+	For: @property
+	Initial: n/a (see prose)
+	
+ +Specifies the syntax of the custom property, +in the form defined by [[#syntax-strings]]. +This descriptor is equivalent to the {{PropertyDescriptor/syntax|syntax}} member of {{PropertyDescriptor}}. + +The 'syntax' descriptor is required for the ''@property'' rule to be valid; +if it's missing, the ''@property'' rule is invalid. + +If the provided string does not successfully [=consume a syntax definition|parse as a syntax definition=], +the descriptor is invalid and must be ignored. + + +The 'inherits' descriptor {#inherits-descriptor} +------------------------------------------------ + +
+	Name: inherits
+	Value: true | false
+	For: @property
+	Initial: n/a (see prose)
+	
+ +Specifies whether or not the custom property inherits. +This is equivalent to the {{PropertyDescriptor/inherits}} member of {{PropertyDescriptor}}. + +The inherits descriptor is required for the ''@property'' rule to be valid; +if it's missing, the ''@property'' rule is invalid. + + +The 'initial-value' descriptor {#initial-value-descriptor} +---------------------------------------------------------- + +
+	Name: initial-value
+	Value: <>
+	For: @property
+	Initial: the [=guaranteed-invalid value=] (but see prose)
+	
+ +Specifies the [=initial value=] of the custom property. +This is equivalent to the {{PropertyDescriptor/initialValue}} member of {{PropertyDescriptor}}. + +If the value of the 'syntax' descriptor is the [=universal syntax descriptor=], +then the 'initial-value' descriptor is optional. +If omitted, the initial value of the property is the [=guaranteed-invalid value=]. + +Otherwise, +if the value of the 'syntax' descriptor is not the [=universal syntax descriptor=], +the following conditions must be met for the the ''@property'' rule to be valid: + + * The 'initial-value' descriptor must be present. + * The 'initial-value' descriptor's value must [=consume a syntax definition|parse successfully=] + according to the grammar specified by the [=syntax definition=]. + * The 'initial-value' must be [=computationally independent=]. + +If the above conditions are not met, the ''@property'' rule is invalid. + + +Extensions to the {{CSSRule}} interface {#extensions-to-css-rule-interface} +------------------------------------------------------------------------------------ + +The {{CSSRule}} interface is extended as follows: + +
+partial interface CSSRule {
+    const unsigned short PROPERTY_RULE = 18;
+};
+
+ +The CSSPropertyRule interface {#the-css-property-rule-interface} +----------------------------------------------------------------------------- + +The {{CSSPropertyRule}} interface represents an ''@property'' rule. + +
+[Exposed=Window]
+interface CSSPropertyRule : CSSRule {
+    readonly attribute CSSOMString name;
+    readonly attribute CSSOMString syntax;
+    readonly attribute boolean inherits;
+    readonly attribute CSSOMString? initialValue;
+};
+
+ +
+
name +
+ The custom property name associated with the ''@property'' rule. + +
syntax +
+ The syntax associated with the ''@property'', exactly as specified. + +
inherits +
+ The inherits descriptor associated withthe ''@property'' rule. + +
initialValue +
+ The initial value associated with the ''@property'' rule, + which may not be present. +
+ Examples {#examples} ==================== @@ -918,30 +1070,69 @@ Examples {#examples} Example 1: Using custom properties to add animation behavior {#example-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 1s;
-}
+
+	<script>
+	CSS.registerProperty({
+		name: "--stop-color",
+		syntax: "<color>",
+		inherits: false,
+		initialValue: "rgba(0,0,0,0)"
+	});
+	</script>
 
-.button:hover {
-	--stop-color: green;
-}
+	<style>
+	.button {
+		--stop-color: red;
+		background: linear-gradient(var(--stop-color), black);
+		transition: --stop-color 1s;
+	}
 
-&lt;/style>
+	.button:hover {
+		--stop-color: green;
+	}
+	</style>
+
 
+Example 2: Using ''@property'' to register a property {#example-2}
+------------------------------------------------------------------
+
+	<script>
+		CSS.paintWorklet.addModule('circle.js');
+	</script>
+	<style>
+		@property --radius {
+			syntax: "<length>";
+			inherits: false;
+			initial-value: 0px;
+		}
+
+		div {
+			width: 100px;
+			height: 100px;
+			--radius: 10px;
+			background: paint(circle);
+			transition: --radius 1s;
+		}
+
+		div:hover {
+			--radius: 50px;
+		}
+	</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();
+			}
+	});
 
Security Considerations {#security-considerations}