Title: CSS Animations Level 2 Status: ED Work Status: Exploring Shortname: css-animations-2 Level: 2 Group: csswg ED: https://drafts.csswg.org/css-animations-2/ Editor: L. David Baron, Mozilla https://www.mozilla.org/, https://dbaron.org/, w3cid 15393 Editor: Brian Birtles, Mozilla https://www.mozilla.org/, bbirtles@mozilla.com, w3cid 43194 !Issues List: In Bugzilla Abstract: This CSS module describes a way for authors to animate the values of CSS properties over time, using keyframes. The behavior of these keyframe animations can be controlled by specifying their duration, number of repeats, and repeating behavior. Ignored Vars: auto-rewind
urlPrefix: https://w3c.github.io/web-animations/; type: interface; spec: web-animations text: Animation text: KeyframeEffectReadOnly urlPrefix: https://w3c.github.io/web-animations/; type: method; for: Animation; spec: web-animations text: play() text: pause() urlPrefix: https://w3c.github.io/web-animations/; type: method; for: KeyframeEffectReadOnly; spec: web-animations text: getFrames() urlPrefix: https://w3c.github.io/web-animations/; type: dfn; spec: web-animations text: active duration text: active phase text: active time text: after phase text: animation text: animation class text: animation effect text: animation playback rate text: before phase text: composite operation text: current iteration text: current time text: fill mode text: global animation list text: idle play state text: idle phase text: iteration duration text: iteration start text: pause an animation text: pending play state text: play an animation text: sampling text: start delay text: target element text: target effect text: target effect end text: unresolved
This is a delta specification, meaning that it currently contains only the differences from CSS Animations Level 1 [[!CSS3-ANIMATIONS]]. Once the Level 1 specification is closer to complete, it will be merged with the additions here into a complete level 2 specification.
# Animations # {#animations} ## Owning element ## {#owning-element-section} The owning element of an animation refers to the element or pseudo-element to which the 'animation-name' property was applied that generated the animation. If an animation was generated directly by script (e.g. using the {{CSSAnimation}} constructor) then it has no owning element. If an animation generated using the markup defined in this specification is later disassociated from that markup by an update to the computed value of the 'animation-name' property on the owning element, the animation is disassociated from its owning element (that is, it has no owning element from that point forwards).animation
's initial owning element
is elem
. animation
is disassociated from
element
through an update to the computed value of
elem
's 'animation-name' property.
elem.style.animation = 'spin 1s'; let animation = elem.getAnimations()[0]; // animation's owning element is elem elem.style.animation = ''; // animation no longer has an owning elementNote that although the owning element is often equal to the target element of an animation's target effect, this is not always the case. The following example demonstrates some of the situations where these two elements may differ.
elem.style.animation = 'move 1s'; let animation = elem.getAnimations()[0]; // animation.effect.target == elem == animation's owning element let mutableEffect = animation.effect.clone(); animation.effect = mutableEffect; animation.effect.target = elem2; // animation.effect.target == elem2 != animation's owning element animation.effect = null; // animation.effect.target is undefined != animation's owning element
Initial state | ||||||
---|---|---|---|---|---|---|
Event | A | B | C | D | E | |
Resulting state | {{Animation/play()}} | A | B | A | B | B |
{{Animation/pause()}} | C | D | C | D | D | |
'animation-play-state' → ''running'' | A | A | C | C | A | |
'animation-play-state' → ''paused'' | E | B | D | D | E |
Name: animation-composition Value: <<single-animation-composition> = replace | add | accumulate The values of 'animation-composition' have the meaning defined for the corresponding values of the composite operation defined in Web Animations [[!WEB-ANIMATIONS]]. When specified in a keyframe, 'animation-composition' defines the composite operation to use for each property specified in that keyframe until the next keyframe specifying each property.># Initial: replace Applies to: all elements Inherited: none Percentages: N/A Computed value: list, each item a keyword as specified Animation type: not animatable Canonical order: per grammar
@keyframes heartbeat { from { scale: 1; animation-timing-function: ease-out; } 30% { scale: 1.3; } } .heartbeat { animation: heartbeat 0.3s 2s infinite; } @keyframes throb { 50% { scale: 1.8; } } .icon:mouseover { animation: throb 0.4s add; }If these two animations are applied to the same element, normally only one animation would apply, but by specifying ''add'' as the 'animation-composition' on the second animation, the result of the two animations will be combined. Since CSS Transitions [[CSS3-TRANSITIONS]] have a lower composite order, it is possible to use 'animation-composition' to combine CSS Animations with underlying transitions as in the following example.
.icon { filter: blur(20px); transition: filter 0.5s; } .icon:hover { filter: blur(0px); animation: brightness-pulse 3s infinite add; } @keyframes pulse { 0% { scale: 1.1; filter: brightness(130%); } 10% { scale: 1; filter: brightness(100%); } }Issue: Create pictures of these examples and verify they make sense.
max(min(-start delay, active duration), 0)
* interval end =
max(min(target effect end - start delay,
active duration), 0)
Each time an animation is sampled and is not pending, the events to dispatch are determined by
comparing the animation's phase before and after the sample as follows:
Change | Events dispatched | Elapsed time (ms) |
---|---|---|
idle or before → active | {{animationstart}} | interval start |
idle or before → after ٭ | {{animationstart}} | interval start |
{{animationend}} | interval end | |
active → before | {{animationend}} | interval start |
active → active and the current iteration of the animation's target effect has changed since the previous sample | {{animationiteration}} | (See below) † |
active → after | {{animationend}} | interval end |
after → active | {{animationstart}} | interval end |
after → before ٭ | {{animationstart}} | interval end |
{{animationend}} | interval start | |
not idle and not after→ idle | {{animationcancel}} | The active time of the animation at the moment it was cancelled calculated using a fill mode of both. |
٭ Where multiple events are listed for a state change, all events are dispatched in the order listed and in immediate succession.
† The elapsed time for an {{animationiteration}} event is defined as follows:
1. Let previous current iteration be the current iteration from the previous sample. 1. If previous current iteration is greater than current iteration, let iteration boundary becurrent
iteration + 1
, otherwise let it be current iteration.
1. The elapsed time is the result of evaluating
(iteration boundary - iteration start) ×
iteration duration)
.
Since the elapsed time defined in the table and procedure above is
expressed in milliseconds, it must be divided by 1,000 to produce a value in
seconds before being assigned to the {{AnimationEvent/elapsedTime}} member of
the {{AnimationEvent}}.
# DOM Interfaces # {#interface-dom}
## The CSSAnimation interface ## {#the-CSSAnimation-interface}
[Exposed=Window] interface CSSAnimation : Animation { readonly attribute CSSOMString animationName; };: animationName :: The key used to find matching keyframes rules that define target effect at the point when the animation was created. This is the value of the 'animation-name' property that caused this object to be generated or, if this object was generated using the programming interface, the
animationName
argument
that was passed to the {{CSSAnimation}} constructor.
[Constructor (Animatable? target, CSSOMString animationName, optional (unrestricted double or KeyframeEffectOptions) options, optional CSSOMString defaultEasing = "ease"), Constructor (Animatable? target, CSSOMString animationName, (unrestricted double or KeyframeEffectOptions) options, CSSOMString defaultEasing, AnimationTimeline? timeline)] partial interface CSSAnimation { };The difficulty is with liveness. The most useful and least magical (but most complicated) approach is to define a subclass of {{KeyframeEffectReadOnly}} that has the special behavior of tracking changes to all @keyframes rules that match the supplied name and automatically updating the set of keyframes returned by {{KeyframeEffectReadOnly/getFrames()}} after filling-in the default easing. Something like,
[Exposed=Window, Constructor (CSSOMString keyframesName, CSSOMString defaultEasing)] interface CSSKeyframeEffectReadOnly : KeyframeEffectReadOnly { readonly attribute CSSOMString keyframesName; readonly attribute CSSOMString defaultEasing; };
elem
is initially updated, a user agent may defer recalculating
the computed value of the 'animation' property.
However, the {{Animatable/getAnimations()}} method called on elem
is specified by Web Animations and can return {{CSSAnimation}} objects as
defined in this specification.
Hence, as result of the requirements in this section, the user agent must
calculate the updated value of elem
's 'animation' property and
create the requested {{CSSAnimation}} object before returning its result.
elem.style.animation = 'fadeOut 1s'; elem.getAnimations()[0].pause();