Skip to content

Commit 35141be

Browse files
committed
[css-animations-2] Rewrite keyframe processing to re-use (rather than re-define) the cascade.
Also structure it better editorially.
1 parent 137257a commit 35141be

File tree

1 file changed

+92
-123
lines changed

1 file changed

+92
-123
lines changed

css-animations-2/Overview.bs

+92-123
Original file line numberDiff line numberDiff line change
@@ -258,133 +258,102 @@ from its <a>owning element</a> always causes it to enter (or remain) in the
258258
<a>idle play state</a>.
259259
260260
<h2 id="keyframes">
261-
Declaring Keyframes</h2>
261+
Assembling Keyframes</h2>
262+
263+
<h3 id="keyframe-rules">
264+
Declaring Keyframes: the ''@keyframes'' rule</h3>
265+
266+
See [[css-animations-1#keyframes]].
262267
263268
<h3 id="keyframe-processing">
264269
Processing Keyframes</h3>
265270
266-
For a given target (pseudo-)element, |element|, an animation name, |name|,
267-
and the position of the animation in |element|'s 'animation-name' list,
268-
|position|,
269-
[=keyframe=] objects are generated as follows:
270-
271-
1. Let |default timing function| be
272-
the timing function at position |position|
273-
of the [=resolved value=] of the 'animation-timing-function' for |element|,
274-
repeating the list as necessary as described in
275-
[[CSS-ANIMATIONS-1#animation-name]].
276-
277-
1. Let |default composite| be ''replace''.
278-
279-
1. Find the last ''@keyframes'' at-rule in document order
280-
with <<keyframes-name>> matching |name|.
281-
282-
If there is no ''@keyframes'' at-rule
283-
with <<keyframes-name>> matching |name|,
284-
abort this procedure.
285-
In this case no animation is generated,
286-
and any existing animation matching |name| is canceled.
287-
288-
1. Let |keyframes| be an empty sequence of [=keyframe=] objects.
289-
290-
1. Let |animated properties| be an empty set of longhand CSS property names.
291-
292-
1. Perform a stable sort of the keyframe blocks in the ''@keyframes'' rule
293-
by the offset specified in the keyframe selector,
294-
and iterate over the result in reverse
295-
applying the following steps:
296-
297-
1. Let |keyframe offset| be the value of the keyframe selector
298-
converted to a value in the range 0 &le; |keyframe offset| &le; 1.
299-
300-
1. Let |keyframe timing function| be the value of
301-
the last valid declaration of 'animation-timing-function'
302-
specified on the keyframe block, or,
303-
if there is no such valid declaration, |default timing function|.
304-
305-
1. Let |keyframe composite| be the value of
306-
the last valid declaration of 'animation-composition'
307-
specified on the keyframe block, or,
308-
if there is no such valid declaration, |default composite|.
309-
310-
1. After converting |keyframe timing function| to its canonical form
311-
(e.g. such that ''step-end'' becomes ''steps(1, end)'')
312-
let |keyframe| refer to the existing keyframe in |keyframes| with
313-
matching keyframe offset, timing function and composite, if any.
314-
315-
If there is no such existing keyframe,
316-
let |keyframe| be a new empty keyframe with
317-
offset, |keyframe offset|,
318-
timing function, |keyframe timing function|,
319-
composite, |keyframe composite|,
320-
and prepend it to |keyframes|.
321-
322-
1. Iterate over all declarations in the keyframe block and
323-
add them to |keyframe| such that:
324-
325-
* Each shorthand property is expanded to its longhand
326-
subproperties.
327-
328-
* All logical properties are converted to their
329-
[[css-writing-modes-4#logical-to-physical|equivalent physical properties]].
330-
331-
* For any expanded physical longhand properties that appear more
332-
than once,
333-
only the last declaration in source order is added.
334-
335-
Note, since multiple keyframe blocks may specify the same
336-
|keyframe offset|,
337-
and since this algorithm iterates over these blocks in reverse,
338-
this implies that if any properties are encountered that
339-
have already added at this same |keyframe offset|,
340-
they should be skipped.
341-
342-
1. Add each property name that was added to |keyframe|
343-
to |animated properties|.
344-
345-
1. If there is no keyframe in |keyframes| with offset 0,
346-
or if amongst the keyframes in |keyframes| with offset 0
347-
not all of the properties in |animated properties| are present,
348-
349-
1. Let |initial keyframe| be the [=keyframe=] in |keyframes|
350-
with offset 0, timing function |default timing function|
351-
and composite |default composite|.
352-
353-
If there is no such keyframe,
354-
let |initial keyframe| be a new empty keyframe with offset 0,
355-
timing function |default timing function|,
356-
composite |default composite,
357-
and add it to |keyframes| after the last keyframe with offset 0.
358-
359-
1. For each property in |animated properties| that is not present
360-
in some other keyframe with offset 0,
361-
add the [=computed value=] of that property for |element|
362-
to the keyframe.
363-
364-
1. Similarly, if there is no keyframe in |keyframes| with offset 1,
365-
or if amongst the keyframes in |keyframes| with offset 1
366-
not all of the properties in |animated properties| are present,
367-
368-
1. Let |final keyframe| be the [=keyframe=] in |keyframes|
369-
with offset 1, timing function |default timing function|
370-
and composite |default composite|.
371-
372-
If there is no such keyframe,
373-
let |final keyframe| be a new empty keyframe with offset 1,
374-
timing function |default timing function|
375-
and composite |default composite|,
376-
and add it to |keyframes| after the last keyframe with offset 1.
377-
378-
1. For each property in |animated properties| that is not present
379-
in some other keyframe with offset 1,
380-
add the [=computed value=] of that property for |element|
381-
to the keyframe.
382-
383-
Issue: The above procedure requires iterating over keyframe blocks in reverse.
384-
It could be rewritten so this is not required but that will likely change
385-
the behavior for some edge cases.
386-
We should verify what current implementations do and possible remove the
387-
requirement to iterate in reverse.
271+
For each animation effect defined by the <var>N</var>th item
272+
in the [=coordinated value list=] of the 'animation-*' properties
273+
on target (pseudo-)element |element|,
274+
its associated [=keyframes=] are generated as follows:
275+
276+
1. <strong>Set Defaults:</strong>
277+
278+
* Let |default timing function| be the corresponding [=computed value=]
279+
of 'animation-timing-function' on |element|.
280+
281+
* Let |default composite| be ''replace''.
282+
283+
* Let |keyframes| be an empty sequence of [=keyframe=] objects,
284+
each possessing a
285+
|keyframe offset|,
286+
|keyframe timing function|,
287+
|keyframe composite|,
288+
and |keyframe values|.
289+
290+
* Let |animated properties| be an empty set of CSS property names.
291+
292+
1. <strong>Collect Declared Keyframes:</strong>
293+
1. Find the last ''@keyframes'' at-rule in document order
294+
with <<keyframes-name>> matching
295+
the corresponding 'animation-name' value |name|.
296+
297+
If there is no ''@keyframes'' at-rule
298+
with <<keyframes-name>> matching |name|
299+
(or if |name| is ''animation-name/none''),
300+
abort this procedure.
301+
In this case no animation is generated,
302+
and any existing animation matching |name| is canceled.
303+
304+
1. Perform a stable sort on all [=keyframe blocks=] in the ''@keyframes'' rule
305+
by their specified <<keyframe-selector>>
306+
(treating ''@keyframe/from'' as ''0%'' and ''@keyframe/to'' as ''100%'').
307+
308+
1. Group together all [=keyframe blocks=]
309+
that share the same [=specified value|specified=] <<keyframe-selector>>
310+
(treating ''@keyframe/from'' as ''0%'' and ''@keyframe/to'' as ''100%''),
311+
last declared 'animation-timing-function' [=computed value=]
312+
(defaulting to |default timing function| if there is no such declaration),
313+
and last declared 'animation-composition' [=computed value=]
314+
(defaulting to |default composite| if there is no such declaration).
315+
316+
1. For each such group of matching [=keyframe blocks=],
317+
ordered by their earliest [=keyframe block=] in the sorted order:
318+
319+
1. [=Cascade=] together all of its [=declaration blocks=]
320+
such that for each CSS property
321+
(except those that are “not animatable”, which must be ignored)
322+
the last declaration among all its [=keyframe blocks=]
323+
takes precedence.
324+
[[CSS-CASCADE-4]]
325+
326+
Note: The [=cascade=] will
327+
expand [=shorthand properties=] into their [=sub-properties=]
328+
and map together corresponding property pairs in each [=logical property group=]
329+
according to the |element|’s [=computed value|computed=] [=writing mode=].
330+
331+
1. Append to |keyframes| a new empty [=keyframe=] |keyframe|
332+
with the group’s |keyframe offset|,
333+
|keyframe timing function|,
334+
and |keyframe composite|.
335+
Give its |keyframe values|
336+
the set of [=declared values=] resulting from this cascade.
337+
338+
1. Add each property name that was added to its |keyframe properties|
339+
to |animated properties|.
340+
341+
1. <strong>Generate Initial and Final Frames:</strong>
342+
343+
1. Create two new [=keyframes=], |initial keyframe| and |final keyframe|,
344+
assigning each |default timing function| as its |keyframe timing function|
345+
and |default composite| as its |keyframe composite|.
346+
347+
1. Give |initial keyframe| a |keyframe offset| of zero (''0%'')
348+
and prepend it to |keyframes|;
349+
give |final keyframe| a |keyframe offset| of one (''100%'')
350+
and append it to |keyframes|.
351+
352+
1. Add to the |keyframe properties| of |initial keyframe| and |final keyframe|
353+
the [=computed value=] on |element|
354+
of each property in |animated properties|
355+
that is not already assigned to a [=keyframe=] in |keyframes|
356+
that has a matching |keyframe offset|.
388357
389358
<h2 id="animation-definition">
390359
Declaring Animations</h2>

0 commit comments

Comments
 (0)