-
Notifications
You must be signed in to change notification settings - Fork 143
/
Copy pathOverview.bs
509 lines (414 loc) · 18.6 KB
/
Overview.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
<pre class='metadata'>
Title: CSS Properties and Values API Level 1
Status: ED
Group: houdini
ED: https://drafts.css-houdini.org/css-properties-values-api-1/
Previous Version: http://www.w3.org/TR/2016/WD-css-properties-values-api-1-20160607/
Shortname: css-properties-values-api
Level: 1
Abstract: This CSS module defines an API for registering new CSS properties. Properties registered using this API are provided with a parse syntax that defines a type, inheritance behaviour, and an initial value.
Editor: Tab Atkins, jackalmage@gmail.com
Editor: Shane Stephens, shanestephens@google.com
Editor: Daniel Glazman, daniel.glazman@disruptive-innovations.com
Editor: Alan Stearns, stearns@adobe.com
Editor: Elliot Sprehn, esprehn@chromium.org
Editor: Greg Whitworth, gwhit@microsoft.com
Ignored Terms: boolean, Animatable, Map, Context, isolated worker, SyntaxError,
Ignored Terms: InvalidModificationError, NotFoundError, StylePropertyMapReadOnly,
Ignored Terms: worklet global scope
Ignored Terms: throw, NotSupportedError, isconstructor, get, iscallable,
Ignored Terms: construct, name map of inputs
Ignored Vars: arguments, methodPropertyKey, inputStyleMap, workletGlobalScope
Ignored Terms: WorkletGlobalContext
Repository: w3c/css-houdini-drafts
</pre>
<pre class='biblio'>
{
"css-paint-api": {
"title": "CSS Painting API"
},
"css-layout-api": {
"title": "CSS Layout API"
}
}
</pre>
<pre class='link-defaults'>
spec:css-transforms-1; type:type; text:<transform-function>
spec:cssom-1; type:interface; text:CSS
spec:css-color-4; type:property; text:color
spec:dom;
type:dfn; text:ascii case-insensitive
type:interface; text:Document
</pre>
Introduction {#intro}
=====================
CSS defines a comprehensive set of properties that can be manipulated in order
to modify the layout, paint, or behaviour of a web document. However, web authors
frequently wish to extend this set with additional properties.
[[css-variables]] provides primitive means for defining user-controlled properties,
however these properties always take token lists as values, must always inherit, and
can only impact document layout or paint by being re-incorporated into the value
of other properties via a var() reference.
This specification extends [[css-variables]], allowing the registration of properties
that have a value type, an initial value, and a defined inheritance behaviour.
This specification is complementary to [[css-paint-api]] and [[css-layout-api]], which
allow custom properties to directly impact paint and layout behaviours respectively.
Registering custom properties {#registering-custom-properties}
==============================================================
<pre class='idl'>
dictionary PropertyDescriptor {
required DOMString name;
DOMString syntax = "*";
boolean inherits = false;
DOMString initialValue;
};
partial interface CSS {
static void registerProperty(PropertyDescriptor descriptor);
static void unregisterProperty(DOMString name);
};
</pre>
Additional, the {{Document}} object gains a new <dfn attribute for=Window>\[[registeredPropertySet]]</dfn> private slot,
which is a set of records that describe registered custom properties.
The {{PropertyDescriptor}} dictionary {#the-propertydescriptor-dictionary}
--------------------------------------------------------------------------
A <dfn>PropertyDescriptor</dfn> dictionary represents author-specified configuration
options for a custom property. {{PropertyDescriptor}} dictionaries contain the
following members:
: <dfn dict-member for=PropertyDescriptor>name</dfn>
:: The name of the custom property being defined.
: <dfn dict-member for=PropertyDescriptor>syntax</dfn>
:: A string representing how this custom property is parsed.
: <dfn dict-member for=PropertyDescriptor>inherits</dfn>
:: True if this custom property should inherit down the DOM tree; False otherwise.
: <dfn dict-member for=PropertyDescriptor>initialValue</dfn>
:: The initial value of this custom property.
The {{registerProperty()}} and {{unregisterProperty()}} functions {#the-registerproperty-function}
--------------------------------------------------------------------------------------------------
The <dfn method for=CSS>registerProperty(PropertyDescriptor descriptor)</dfn> method
registers a custom property according to the configuration options provided in
<code>descriptor</code>.
When it is called,
it executes the <a>register a custom property</a> algorithm,
passing the options in its <code>descriptor</code> argument
as arguments of the same names.
<div algorithm>
To <dfn>register a custom property</dfn>
with |name| being a string,
and optionally
|syntax| being a string,
|inherits| being a boolean,
and |initialValue| being a string,
execute these steps:
1. Let |property set|
be the value of the
<a>current global object's</a>
<a>associated <code>Document</code></a>'s
{{[[registeredPropertySet]]}} slot.
2. Attempt to parse |name|
as a <<custom-property-name>>.
If this fails,
<a>throw</a> a {{SyntaxError}}
and exit this algorithm.
Otherwise,
let |parsed name| be the parsed value.
If |property set|
already contains an entry with |parsed name| as its property name
(compared codepoint-wise),
<a>throw</a> an {{InvalidModificationError}}
and exit this algorithm.
3. If |syntax| is not present,
or is equal to <code>"*"</code> (U+002A ASTERISK),
let |parsed syntax| be undefined,
and skip to the next step of this algorithm.
Otherwise, attempt to parse |syntax|
according to the rules in [[#supported-syntax-strings]].
If it does not parse successfully,
<a>throw</a> a {{SyntaxError}}.
Otherwise,
let |parsed syntax| be the parsed syntax.
Note: For example, a valid syntax string is something like <code>"<length>"</code>,
or <code>"<number>+"</code>;
the allowed syntax is a subset of [[css-values-3#value-defs]].
Future levels of this specification are expected to expand the complexity of allowed syntax strings,
allowing custom properties that more closely resemble the full breadth of what CSS properties allow.
4. If |parsed syntax| is undefined,
and |initialValue| is not present,
let |parsed initial value| be empty.
This must be treated identically to the "default" initial value of custom properties,
as defined in [[!css-variables]].
Skip to the next step of this algorithm.
Otherwise,
if |parsed syntax| is undefined,
parse |initialValue| as a <<declaration-value>>.
If this fails,
<a>throw</a> a {{SyntaxError}}
and exit this algorithm.
Otherwise,
let |parsed initial value| be the parsed result.
Skip to the next step of this algorithm.
Otherwise, if |initialValue| is not present,
<a>throw</a> a {{SyntaxError}}
and exit this algorithm.
Otherwise,
parse {{PropertyDescriptor/initialValue}}
according to |parsed syntax|.
If this fails,
<a>throw</a> a {{SyntaxError}}
and exit this algorithm.
Otherwise, let |parsed initial value| be the parsed result.
If |parsed initial value| is not <a>computationally independent</a>,
<a>throw</a> a {{SyntaxError}}
and exit this algorithm.
5. If |inherits| is present,
set |inherit flag| to its value.
Otherwise, set |inherit flag| to false.
6. Let |registered property| be a record
with a property name of |parsed name|,
a syntax of |parsed syntax|,
an initial value of |parsed initial value|,
and an inherit flag of |inherit flag|.
Add |registered property|
to |property set|.
</div>
A property value is <dfn export>computationally independent</dfn>
if it can be converted into a computed value
using only the value of the property on the element,
and "global" information that cannot be changed by CSS.
<div class='example'>
For example, ''5px'' is <a>computationally independent</a>,
as converting it into a computed value doesn't change it at all.
Similarly, ''1in'' is <a>computationally independent</a>,
as converting it into a computed value
relies only on the "global knowledge" that ''1in'' is ''96px'',
which can't be altered or adjusted by anything in CSS.
On the other hand, ''3em'' is not <a>computationally independent</a>,
because it relies on the value of 'font-size' on the element
(or the element's parent).
Neither is a value with a ''var()'' function,
because it relies on the value of a <a>custom property</a>.
</div>
When a custom property is registered with a given type,
the process via which specified values for that property are turned into computed values
is defined fully by the type selected,
as described in [[#calculation-of-computed-values]].
Properties can be unregistered using
<dfn method for=CSS>unregisterProperty(DOMString name)</dfn>.
When it is called,
it executes the <a>unregister a custom property</a> algorithm,
with a <code>name</code> set to its sole argument.
<div algorithm>
To <dfn>unregister a custom property</dfn> with the name |name|:
1. Let |property set|
be the value of the
<a>current global object's</a>
<a>associated <code>Document</code></a>'s
{{[[registeredPropertySet]]}} slot.
2. Attempt to parse |name|
as a <<custom-property-name>>.
If this fails,
<a>throw</a> a {{SyntaxError}}
and exit this algorithm.
Otherwise,
let |parsed name| be the parsed value.
3. If |property set|
contains a record with a property name matching |parsed name|
(compared codepoint-wise),
remove the record from |property set|.
Otherwise,
<a>throw</a> a {{NotFoundError}}.
</div>
When the <a>current global object's</a> <a>associated <code>Document</code></a>'s {{[[registeredPropertySet]]}} changes,
previously syntactically invalid property values can become valid and vice versa.
This can change the set of <a>declared values</a> which requires the <a>cascade</a> to be recomputed.
<div class='example'>
By default, all custom property declarations that can be parsed as a sequence of tokens
are valid. Hence, the result of this stylesheet:
<pre class='lang-css'>
.thing {
--my-color: green;
--my-color: url("not-a-color");
color: var(--my-color);
}
</pre>
is to set the 'color' property of elements of class "thing" to ''inherit''.
The second '--my-color' declaration overrides the first at parse time (both are valid),
and the ''var()'' reference in the 'color' property is found to be <a spec=css-variables>invalid at computed-value time</a>
(because ''url("not-a-color")'' is not a color).
At this stage of the CSS pipeline (computation time), the only available fallback is the initial value
of the property, which in the case of color is ''inherit''. Although there was a valid usable value
(green), this was removed during parsing because it was superseded by the URL.
if we call:
<pre class='lang-javascript'>
CSS.registerProperty({
name: "--my-color",
syntax: "<color>",
initialValue: "black"
});
</pre>
then the second '--my-color' declaration becomes syntactically invalid at parse time,
and is ignored.
The first '--my-color' is the only valid declaration left for the property,
so 'color' is set to the value ''green''.
</div>
Supported syntax strings {#supported-syntax-strings}
----------------------------------------------------
The following syntax strings are supported:
: "<length>"
:: Any valid <<length>> value
: "<number>"
:: <<number>> values
: "<percentage>"
:: Any valid <<percentage>> value
: "<length-percentage>"
:: Any valid <<length>> or <<percentage>> value, any valid <<calc()>>
expression combining <<length>> and <<percentage>> components.
: "<color>"
:: Any valid <<color>> value
: "<image>"
:: Any valid <<image>> value
: "<url>"
:: Any valid <<url>> value
: "<integer>"
:: Any valid <<integer>> value
: "<angle>"
:: Any valid <<angle>> value
: "<time>"
:: Any valid <<time>> value
: "<resolution>"
:: Any valid <<resolution>> value
: "<transform-function>"
:: Any valid <<transform-function>> value
: "<custom-ident>"
:: Any valid <<custom-ident>> value
: Any sequence consisting of a <a>name-start code point</a>,
followed by zero or more <a>name code points</a>,
which matches the <<custom-ident>> production
:: That identifier
Note: <<custom-ident>>s are compared codepoint-wise with each other;
this is different than the normal behavior of UA-defined CSS
which limits itself to ASCII
and is <a>ASCII case-insensitive</a>.
So, specifying an ident like <code>Red</code>
means that the precise value ''Red'' is accepted;
''red'', ''RED'', and any other casing variants are not matched by this.
It is recommended that idents be restricted to ASCII and written in lower-case,
to match CSS conventions.
: Any one of the preceding strings, followed by '+'
:: A space-separated list of one or more repetitions of the type specified by the string.
: Any combination of the preceding, separated by '|'
:: Any value that matches one of the items in the combination, matched in specified order.
Note: That is, given the syntax string <code>"red | <color>"</code>,
matching the value ''red'' against it will parse as an identifier,
while matching the value ''blue'' will parse as a <<color>>.
: "*"
:: Any valid token stream
Note: [[css3-values]] maintains a distinction between properties that accept
only a length, and properties that accept both a length and a percentage,
however the distinction doesn't currently cleanly line up with the productions.
Accordingly, this specification introduces the length-percentage production
for the purpose of cleanly specifying this distinction.
Regardless of the syntax specified, all custom properties will accept
<a>CSS-wide keywords</a> as well as ''revert'', and process these values
appropriately.
Note: This does not apply to the {{PropertyDescriptor/initialValue}} member
of the {{PropertyDescriptor}} dictionary.
<div class='example'>
For example, the following are all valid syntax strings.
: <code>"<length>"</code>
:: accepts length values
: <code>"<length> | <percentage>"</code>
:: accepts lengths, percentages, percentage calc expressions, and length calc
expressions, but not calc expressions containing a combination of length
and percentage values.
: <code>"<length-percentage>"</code>
:: accepts all values that <code>"<length> | <percentage>"</code> would
accept, as well as calc expressions containing a combination of both length
and percentage values.
: <code>"big | bigger | BIGGER"</code>
:: accepts the ident "big", or the ident "bigger", or the ident "BIGGER".
: <code>"<length>+"</code>
:: accepts a list of length values.
</div>
Calculation of Computed Values {#calculation-of-computed-values}
----------------------------------------------------------------
The syntax of a custom property fully determines how computed values are
generated from specified values for that property.
The <a>CSS-wide keywords</a> and ''revert'' generate computed values as
described in [[!css3-values]] and [[!css-cascade-4]] respectively. Otherwise:
For <length> values, the computed value is the absolute length expressed in pixels.
For <length-percentage> values, the computed value is one of the following:
* if the specified value contains only length units, the computed value is the absolute length
expressed in pixels.
* if the specified value contains only percentages, the computed value is a
simple percentage.
* otherwise, the computed value is a calc expression containing an absolute
length expressed in pixels, and a percentage value.
For <custom-ident>, ident, <color>, <image>, <url>, <integer>,
<angle>, <time>, <resolution> or "*" values, the
computed value is as specified.
For <number> and <percentage> values which are not calc expressions, the
computed value is as specified. Calc expressions that are
<number> and <percentage> values get reduced during computation to simple
numbers and percentages respectively.
For <transform-function> values, the computed value is as specified but with
all lengths resolved to their computed values.
For values specified by a syntax string that include "|" clauses, the computed
value is given by applying the calculation rules for the first clause that
matches to the specified value.
For list values, the computed value is a list of the computed values of the
primitives in the list.
Behavior of Custom Properties {#behavior-of-custom-properties}
==============================================================
Animation Behavior of Custom Properties {#animation-behavior-of-custom-properties}
----------------------------------------------------------------------------------
Note: As defined by [[css3-animations]] and [[css3-transitions]], it is possible to
specify animations and transitions that reference custom properties.
When referenced by animations and transitions,
custom properties interpolate in a manner defined by their types.
If their type is defined as a list with "+",
it's interpolated as a simple list [[!css3-transitions]].
If the start and end of an interpolation have matching types, then they
will interpolate as specified in [[!css3-animations]].
Otherwise, the interpolation falls back to the default 50% flip described in
[[!css3-animations]].
Issue: Intermediate interpolated results of animations on custom properties must
be able to generate a token stream representing their value. We should ensure that
this is standard across implementations to avoid interop issues.
Conditional Rules {#conditional-rules}
--------------------------------------
''@supports'' rules and the {{CSS/supports(conditionText)}} method behave as specified
in [[!css-variables]].
Note: In other words, for the purpose of determining whether a value is
supported by a given custom property, the type registered for the custom property is
ignored and any value consisting of at least one token is considered valid.
Issue(118): should @supports pay attention to type when considering custom properties?
Examples {#examples}
====================
Example 1: Using custom properties to add animation behavior {#example-1}
-------------------------------------------------------------------------
<pre class='lang-markup'>
<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;
}
.button:hover {
--stop-color: green;
}
</style>
</pre>
Security Considerations {#security-considerations}
==================================================
There are no known security issues introduced by these features.
Privacy Considerations {#privacy-considerations}
==================================================
There are no known privacy issues introduced by these features.