CSS Animation Worklet API

CSS Animation Worklet API

W3C First Public Working Draft,

This version:
https://www.w3.org/TR/2019/WD-css-animation-worklet-1-20190625/
Latest published version:
https://www.w3.org/TR/css-animation-worklet-1/
Editor's Draft:
https://drafts.css-houdini.org/css-animationworklet-1/
Feedback:
public-houdini@w3.org with subject line “[css-animation-worklet] … message topic …” (archives)
Issue Tracking:
Inline In Spec
GitHub Issues
Editors:

Abstract

The Animation Worklet API provides a method to create scripted animations that control a set of animation effects. The API is designed to make it possible for user agents to run such animations in their own dedicated thread to provide a degree of performance isolation from main thread.

Status of this document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

This document is a First Public Working Draft.

Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

GitHub Issues are preferred for discussion of this specification. When filing an issue, please put the text “css-animation-worklet” in the title, preferably like this: “[css-animation-worklet] …summary of comment…”. All issues and comments are archived.

This document was produced by the CSS Working Group.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 March 2019 W3C Process Document.

1. Introduction

This section is not normative.

This document introduces a new primitive that provides extensibility in web animations and enables high performance interactive procedural animations on the web. For details on the rationale and motivation see both [explainer] and [principles].

The Animation Worklet API provides a method to create scripted animations that control a set of animation effects. The API is designed to make it possible for user agents to run such animations in their own dedicated thread to provide a degree of performance isolation from main thread.

1.1. Relationship to the Web Animations API

This section is not normative.

Animations running inside an Animation Worklet execution context expose the Animation interface from the Web Animations specification on the main javascript execution context. This means they can be controlled and inspected from main thread using the same Web Animation APIs.

2. Animation Worklet

Animation Worklet is a Worklet responsible for all classes related to custom animations. The worklet can be accessed via animationWorklet attribute.

The animationWorklet's worklet global scope type is AnimationWorkletGlobalScope.

AnimationWorkletGlobalScope represents the global execution context of animationWorklet.

[Exposed=Window]
partial namespace CSS {
    [SameObject] readonly attribute Worklet animationWorklet;
};

3. Animator

An Animator represents an animation instance that is running on the animation thread. Animators are identified by a unique name and determine how the animation progresses its keyframe effects given current input time. Animator instances live in AnimationWorkletGlobalScope and each one is associated with a WorkletAnimation instance. An animator can only be instantiated by construction of a WorkletAnimation.

Two animators types are supported: StatelessAnimator and StatefulAnimator each providing a different state management strategy.

3.1. StatelessAnimator Interface

This interface represents a stateless animator. This type of animator does not depend on any local state either stored on the instance or global scope. Effectively, the animate function of an StatelessAnimator can be treated as a pure function with the expectation that given the same input, it produces the same output.

[Exposed=AnimationWorklet, Global=AnimationWorklet, Constructor (optional any options)]
interface StatelessAnimator {
};
This is how the class should look.
class FooAnimator extends StatelessAnimator {
    constructor(options) {
        // Called when a new animator is instantiated.
    }
    animate(currentTime, effect) {
        // Animation frame logic goes here.
    }
}

Note: The statelessness allows an animation worklet to perform optimization such as producing multiple animation frames in parallel and performing very cheap teardown and setup. Using StatelessAnimator is highly recommended to enable such optimizations.

3.2. StatefulAnimator Interface

This interface represents a stateful animator. This animator can have local state and animation worklet guarantees that it maintains this state as long as the stateful animator fulfills the contract required by this interface as described following.

Animation worklet maintains a set of WorkletGlobalScopes which may exist across different threads or processes. Animation worklet may temporarily terminate a global scope (e.g., to preserve resources) or move a running animator instance across different global scopes (e.g., if its effect is mutable only in a certain thread). Animation worklet guarantees that a stateful animator instance’s state is maintained even if the instance is respawned in a different global scope.

The basic mechanism for maintaining the state is that the animation worklet snapshots the local state that is exposed via the state function and then reifies it so that it can be passed into the constructor when the animator instance is respawned at a later time in a potentially different global scope. The migrate an animator instance algorithm specifies this process in details.

A user-defined stateful animator is expected to fulfill the required contract which is that its state function returns an object representing its state that can be serialized using structured serialized algorithm and that it can also recreate its state given that same object passed to its constructor.

[Exposed=AnimationWorklet, Global=AnimationWorklet,
Constructor (optional any options, optional any state)]
interface StatefulAnimator {
  any state();
};
This is how the class should look.
class BarAnimator extends StatefulAnimator {
    constructor(options, state) {
      // Called when a new animator is instantiated (either first time or after being respawned).
      this.currentVelocity  = state ? state.velocity : 0;
    }
    animate(currentTime, effect) {
        // Animation frame logic goes here and can rely on this.currentVelocity.
        this.currentVelocity += 0.1;
    }
    state() {
      // The returned object should be serializable using structured clonable algorithm.
      return {
        velocity: this.currentVelocity;
      }
    }
}

3.3. Animator Definition

An animator definition is a struct which describes the author defined custom animation as needed by AnimationWorkletGlobalScope. It consists of:

3.4. Registering an Animator Definition

An AnimationWorkletGlobalScope has a animator name to animator definition map. The map gets populated when registerAnimator(name, animatorCtor) is called.
[ Exposed=AnimationWorklet, Global=AnimationWorklet ]
interface AnimationWorkletGlobalScope : WorkletGlobalScope {
    void registerAnimator(DOMString name, AnimatorInstanceConstructor animatorCtor);
};

callback AnimatorInstanceConstructor = any (any options, optional any state);

When the registerAnimator(name, animatorCtor) method is called in a AnimationWorkletGlobalScope, the user agent must run the following steps:

  1. If name is not a valid <ident>, throw a TypeError and abort all these steps.

  2. If name exists as a key in the animator name to animator definition map, throw a NotSupportedError and abort all these steps.

  3. If the result of IsConstructor(animatorCtor) is false, throw a TypeError and abort all these steps.

  4. Let prototype be the result of Get(animatorCtor, "prototype").

  5. If SameValue(prototype, StatelessAnimator) is true set stateful to be false, otherwise if SameValue(prototype, StatefulAnimator) is true set stateful to be true, otherwise throw a TypeError and abort all these steps.

  6. Let animateValue be the result of Get(prototype, "animate").

  7. Let animate be the result of converting animateValue to the Function callback function type. If an exception is thrown, rethrow the exception and abort all these steps.

  8. Let definition be a new animator definition with:

  9. Add the key-value pair (name - definition) to the animator name to animator definition map.

4. Animator Instance

An animator instance is a struct which describes a fully realized custom animation instance in an AnimationWorkletGlobalScope. It has a reference to an animator definition and owns the instance specific state such as animation effect and timeline. It consists of:

A stateful animator instance is an animator instance whose corresponding animator definition’s stateful flag is true.

4.1. Creating an Animator Instance

Each animator instance lives in an AnimationWorkletGlobalScope.

Each AnimationWorkletGlobalScope has an animator instance set. The set is populated when the user agent constructs a new animator instance in the AnimationWorkletGlobalScope scope. Each animator instance corresponds to a worklet animation in the document scope.

To create a new animator instance given a name, timeline, effect, serializedOptions, serializedState, and workletGlobalScope, the user agent must run the following steps:

  1. Let the definition be the result of looking up name on the workletGlobalScope’s animator name to animator definition map.

    If definition does not exist abort the following steps.

  2. Let animatorCtor be the class constructor of definition.

  3. Let options be StructuredDeserialize(serializedOptions).

  4. Let state be StructuredDeserialize(serializedState).

  5. Let animatorInstance be the result of constructing animatorCtor with «options, state» as arguments. If an exception is thrown, rethrow the exception and abort all these steps.

  6. Set the following on animatorInstance with:

  7. Add animatorInstance to workletGlobalScope’s animator instance set.

4.2. Running Animators

When the user agent wants to produce a new animation frame, if for any animator instance the associated animation requested flag is frame-requested then the the user agent must run animators for the current frame.

Note: The user agent is not required to run animations on every visual frame. It is legal to defer generating an animation frame until a later frame. This allow the user agent to provide a different service level according to their policy.

When the user agent wants to run animators in a given workletGlobalScope, it must iterate over all animator instances in the workletGlobalScope’s animator instance set. For each such instance the user agent must perform the following steps:

  1. Let animatorName be instance’s animator name

  2. Let the definition be the result of looking up animatorName on the workletGlobalScope’s animator name to animator definition map.

    If definition does not exist then abort the following steps.

  3. If the animation requested flag for instance is frame-current or the effect belonging to the instance will not be visible within the visual viewport of the current frame the user agent may abort all the following steps.

    Consider giving user agents permission to skip running animator instances to throttle slow animators.

  4. Let animateFunction be definition’s animate function.

  5. Let currentTime be animator current time of instance.

  6. Let effect be animator effect of instance.

  7. Invoke animateFunction with arguments «currentTime, effect», and with instance as the callback this value.

Note: Although inefficient, it is legal for the user agent to run animators multiple times in the same frame.

should be explicit as to what happens if the animateFunction throws an exception. At least we should have wording that the localTime values of the keyframes are ignored to avoid incorrect partial updates.

4.3. Removing an Animator Instance

To remove an animator instance given instance and workletGlobalScope the user agent must run the following steps:

  1. Remove instance from workletGlobalScope’s animator instance set.

4.4. Migrating an Animator Instance

The migration process allows stateful animator instance to be migrated to a different WorkletGlobalScope without losing their local state.

To migrate an animator instance from one WorkletGlobalScope to another, given instance, sourceWorkletGlobalScope, destinationWorkletGlobalScope, the user agent must run the following steps :

  1. Let serializedState be undefined.

  2. Queue a task on sourceWorkletGlobalScope to run the following steps:

    1. Let animatorName be instance’s animator name

    2. Let definition be the result of looking up animatorName on sourceWorkletGlobalScope’s animator name to animator definition map.

      If definition does not exist then abort the following steps.

    3. Let stateful be the stateful flag of definition.

    4. If stateful is false then abort the following steps.

    5. stateFunction

    6. Let state be the result of Invoke stateFunction with instance as the callback this value. If any exception is thrown, rethrow the exception and abort the following steps.

    7. Set serializedState to be the result of StructuredSerialize(state). If any exception is thrown, then abort the following steps.

    8. Run the procedure to remove an animator instance given instance, and sourceWorkletGlobalScope.

  3. Wait for the above task to complete. If the task is aborted, abort the following steps.

  4. Queue a task on destinationWorkletGlobalScope to run the following steps:

    1. Run the procedure to create a new animator instance given:

If an animator state getter throws the user agent will remove the animator but does not recreate it. This effectively removes the animator instance.

4.5. Requesting Animation Frames

Each animator instance has an associated animation requested flag. It must be either frame-requested or frame-current. It is initially set to frame-current. Different circumstances can cause the animation requested flag to be set to frame-requested. These include the following:

§4.2 Running Animators resets the animation requested flag on animators to frame-current.

5. Web Animations Integration

5.1. Worklet Animation

Worklet animation is a kind of animation that delegates the animation playback to an animator instance. It controls the lifetime and playback state of its corresponding animator instance.

Being an animation, worklet animation has an animation effect and a timeline. However unlike other animations the worklet animation’s current time does not directly determine the animation effect’s local time (via its inherited time). Instead the associated animator instance controls the animation effect’s local time directly. Note that this means that the timeline’s current time does not fully determine the animation’s output.

Worklet animation has the following properties in addition to the Animation interface:

Overview of the WorkletAnimation timing model.
Overview of the WorkletAnimation timing model.

The animation current time is input to the animator instance, which produces a local time value for the animation effect. If the animator instance is running in a parallel global scope the implementation may also choose to use the local time value to produce the final effect value and update the visuals in parallel.

5.2. Creating a Worklet Animation

[Exposed=Window,
 Constructor (DOMString animatorName,
              optional (AnimationEffect or sequence<AnimationEffect>)? effects = null,
              optional AnimationTimeline? timeline,
              optional any options)]
interface WorkletAnimation : Animation {
        readonly attribute DOMString animatorName;
};

WorkletAnimation(animatorName, effects, timeline, options)

Creates a new WorkletAnimation object using the following procedure.

  1. Let workletAnimation be a new WorkletAnimation object.

  2. Run the procedure to set the timeline of an animation on workletAnimation passing timeline as the new timeline or, if a timeline argument is not provided, passing the default document timeline of the Document associated with the Window that is the current global object.

  3. Let effect be the result corresponding to the first matching condition from below.

    If effects is a AnimationEffect object,

    Let effect be effects.

    If effects is a list of AnimationEffect objects,

    Let effect be a new WorkletGroupEffect with its children set to effects.

    Otherwise,

    Let effect be undefined.

  4. Run the procedure to set the target effect of an animation on workletAnimation passing effect as the new effect.

  5. Let serializedOptions be the result of StructuredSerialize(options). Rethrow any exceptions.

  6. Set the serialized options of workletAnimation to serializedOptions.

  7. Set the animation animator name of workletAnimation to animatorName.

5.3. Worklet Animation timing model

This section describes how worklet animation’s timing model differs from other animations.

In addition to the existing conditions on when the animation is considered ready, a worklet animation is only considered ready when the following condition is also true:

As described in §5.1 Worklet Animation, the worklet animation’s current time does not determine its animation effect’s local time. Instead the associated animator instance controls the animation effect’s local time directly. This means that the animation effect’s local time is controlled from a WorkletGlobalScope which may be in a parallel execution context.

Here are a few implications of the above semantics:

If a Worklet Animation animation is executing in a parallel worklet execution context, the last known state of its animation effects should be periodically synced back to the main javascript execution context. The synchronization of effect values from the parallel worklet execution context to the main javascript execution context must occur before running the animation frame callbacks as part of the document lifecycle. Note that due to the asynchronous nature of this animation model a script running in the main javascript execution context may see a stale value when reading a target property that is being animated by a Worklet Animation, compared to the value currently being used to produce the visual frame that is visible to the user. This is similar to the effect of asynchronous scrolling when reading scroll offsets in the main javascript execution context.

Come with appropriate mechanism’s for animator instance to get notified when its animation currentTime is changing e.g., via reverse(), finish() or playbackRate change. So that it can react appropriately. <https://github.com/w3c/css-houdini-drafts/issues/811>

5.4. Interaction with Animator Instances

A worklet animation corresponds to at most one animator instance at any time, and may have no current corresponding animator instance. The correspondance of an animator instance for a worklet animation depends on the animation play state.

To associate animator instance of worklet animation given workletAnimation, the user agent must run the following steps:

  1. If workletAnimation has a corresponding animator instance, abort the following steps.

  2. Let workletGlobalScope be the AnimationWorkletGlobalScope associated with workletAnimation.

  3. Queue a task on workletGlobalScope to run the procedure to create a new animator instance, passing:

  4. If the procedure was successful, set the resulting animator instance as corresponding to workletAnimation.

To disassociate animator instance of worklet animation given workletAnimation, the user age must run the following steps:

  1. If workletAnimation does not have a corresponding animator instance, abort the following steps.

  2. Let workletGlobalScope be the AnimationWorkletGlobalScope associated with workletAnimation.

  3. Let animatorInstance be workletAnimation’s corresponding animator instance.

  4. Queue a task on the workletGlobalScope to run the procedure to remove an animator instance, passing animatorInstance as instance and workletGlobalScope as workletGlobalScope.

  5. Set workletAnimation as having no corresponding animator instance.

To set animator instance of worklet animation given workletAnimation, the user agent must run the following steps:

  1. disassociate animator instance of worklet animation given workletAnimation.

  2. associate animator instance of worklet animation given workletAnimation.

When a given workletAnimation’s play state changes to pending, running, or paused, run the procedure to associate animator instance of worklet animation given workletAnimation.

When a given workletAnimation’s play state changes to idle or finished, run the procedure to disassociate animator instance of worklet animation given workletAnimation.

When the procedure to set the target effect of an animation for a given workletAnimation is called, then set animator instance of worklet animation given workletAnimation.

When the procedure to set the timeline of an animation for a given workletAnimation is called, then set animator instance of worklet animation given workletAnimation.

5.5. ScrollTimeline

This section is not normative.

ScrollTimeline is a new concept being proposed for addition to web animation API. It defines an animation timeline whose time value depends on the scroll position of a scroll container. Worklet animations can have a scroll timeline and thus drive their scripted effects based on a scroll offset.

Note: Access to input: We are interested on exposing additional user input beside scrolling (e.g., touch/pointer input) to these animations so that authors can create jank-free input driven animations which are not really possible today. We are still trying to figure out the right abstractions and mechanisms to do this.

5.6. WorkletGroupEffect

WorkletGroupEffect is a type of group effect that allows its child effect’s local times to be mutated individually.

When a WorkletGroupEffect is set as the animation effect of a WorkletAnimation, the corresponding animator instance can directly control the child effects' local times. This allows a single worklet animation to coordinate multiple effects - see §8.2 Example 2: Parallax backgrounds. for an example of such a use-case.

[Exposed=AnimationWorklet]
interface WorkletGroupEffect {
  sequence<AnimationEffect> getChildren();
};

[Exposed=AnimationWorklet]
partial interface AnimationEffect {
    // Intended for use inside Animation Worklet scope to drive the effect.
    attribute double localTime;
};

To set the localTime property on a effect to value t, the user agent should perform the action that corresponds to the first matching condition from the following:

If the effect does not have a parent group,

Set the effect local time to t.

If the effect has a parent group and it is of WorkletGroupEffect type,

Set the effect start time to (parent’s transformed time - t). Note this effectively set’s the effect’s local time to t.

Otherwise

Throw an exception indicating that the child effect time can only be controlled by its parent group.

The above interface exposes a conservative subset of GroupEffect proposed as part of web-animation-2. We should instead move this into a delta spec against the web-animation. <https://github.com/w3c/csswg-drafts/issues/2071>

5.7. Effect Stack and Composite Order

As with other animations, worklet animations participate in the effect stack. A worklet animation does not have a specific animation class which means it has the same composite order as other Javascript created web animations.

6. Security Considerations

There are no known security issues introduced by these features.

7. Privacy Considerations

There are no known privacy issues introduced by these features.

8. Examples

8.1. Example 1: Twitter header.

An example of twitter profile header effect where two elements (avatar, and header) are updated in sync with scroll offset.
// In document scope.
<div id='scrollingContainer'>
  <div id='header' style='height: 150px'></div>
  <div id='avatar'><img></div>
</div>

<script>
await CSS.animationWorklet.addModule('twitter-header-animator.js');
const animation = new WorkletAnimation(
    'twitter-header',
    [new KeyframeEffect($avatar,  /* scales down as we scroll up */
                    [{transform: 'scale(1)'}, {transform: 'scale(0.5)'}],
                    {duration: 1000, iterations: 1}),
    new KeyframeEffect($header, /* loses transparency as we scroll up */
                    [{opacity: 0}, {opacity: 0.8}],
                    {duration: 1000, iterations: 1})],
    new ScrollTimeline({
      scrollSource: $scrollingContainer,
      orientation: 'block',
      timeRange: 1000,
      startScrollOffset: 0,
      endScrollOffset: $header.clientHeight}));
animation.play();

// Since this animation is using a group effect, the same animation instance
// is accessible via different handles: $avatarEl.getAnimations()[0], $headerEl.getAnimations()[0]

</script>
// Inside AnimationWorkletGlobalScope.
registerAnimator('twitter-header', class HeaderAnimator extends StatelessAnimator {
  constructor(options) {
    this.timing_ = new CubicBezier('ease-out');
  }

  animate(currentTime, effect) {
    const scroll = currentTime;  // scroll is in [0, 1000] range

    // Drive the output group effect by setting its children local times individually.
    effect.children[0].localTime = scroll;
    effect.children[1].localTime = this.timing_(clamp(scroll, 0, 500));
  }
});

function clamp(value, min, max) {
  return Math.min(Math.max(value, min), max);
}

8.2. Example 2: Parallax backgrounds.

A simple parallax background example.
<style>
.parallax {
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0.5;
}
</style>
<div id='scrollingContainer'>
  <div id="slow" class="parallax"></div>
  <div id="fast" class="parallax"></div>
</div>

<script>
await CSS.animationWorklet.addModule('parallax-animator.js');
const scrollTimeline = new ScrollTimeline({
  scrollSource: $scrollingContainer,
  orientation: 'block',
  timeRange: 1000
});
const scrollRange = $scrollingContainer.scrollHeight - $scrollingContainer.clientHeight;

const slowParallax = new WorkletAnimation(
    'parallax',
    new KeyframeEffect($parallax_slow, [{'transform': 'translateY(0)'}, {'transform': 'translateY(' + -scrollRange + 'px)'}], {duration: 1000}),
    scrollTimeline,
    {rate : 0.4}
);
slowParallax.play();

const fastParallax = new WorkletAnimation(
    'parallax',
    new KeyframeEffect($parallax_fast, [{'transform': 'translateY(0)'}, {'transform': 'translateY(' + -scrollRange + 'px)'}], {duration: 1000}),
    scrollTimeline,
    {rate : 0.8}
);
fastParallax.play();
</script>
// Inside AnimationWorkletGlobalScope.
registerAnimator('parallax', class ParallaxAnimator extends StatelessAnimator {
  constructor(options) {
    this.rate_ = options.rate;
  }

  animate(currentTime, effect) {
    effect.localTime = currentTime * this.rate_;
  }
});

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.

Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
A CSS style sheet.
renderer
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at https://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS-TRANSITIONS-1]
David Baron; et al. CSS Transitions. 11 October 2018. WD. URL: https://www.w3.org/TR/css-transitions-1/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 31 January 2019. WD. URL: https://www.w3.org/TR/css-values-4/
[CSSOM-1]
Simon Pieters; Glenn Adams. CSS Object Model (CSSOM). 17 March 2016. WD. URL: https://www.w3.org/TR/cssom-1/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[WEB-ANIMATIONS-1]
Brian Birtles; et al. Web Animations. 11 October 2018. WD. URL: https://www.w3.org/TR/web-animations-1/
[WebIDL]
Boris Zbarsky. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/
[WORKLETS-1]
Ian Kilpatrick. Worklets Level 1. 7 June 2016. WD. URL: https://www.w3.org/TR/worklets-1/

Informative References

[EXPLAINER]
Animation Worklet Explainer. URL: https://github.com/w3c/css-houdini-drafts/blob/master/css-animationworklet/README.md
[PRINCIPLES]
Animation Worklet Design Principles and Goals. URL: https://github.com/w3c/css-houdini-drafts/blob/master/css-animationworklet/principles.md

IDL Index

[Exposed=Window]
partial namespace CSS {
    [SameObject] readonly attribute Worklet animationWorklet;
};

[Exposed=AnimationWorklet, Global=AnimationWorklet, Constructor (optional any options)]
interface StatelessAnimator {
};

[Exposed=AnimationWorklet, Global=AnimationWorklet,
Constructor (optional any options, optional any state)]
interface StatefulAnimator {
  any state();
};

[ Exposed=AnimationWorklet, Global=AnimationWorklet ]
interface AnimationWorkletGlobalScope : WorkletGlobalScope {
    void registerAnimator(DOMString name, AnimatorInstanceConstructor animatorCtor);
};

callback AnimatorInstanceConstructor = any (any options, optional any state);


[Exposed=Window,
 Constructor (DOMString animatorName,
              optional (AnimationEffect or sequence<AnimationEffect>)? effects = null,
              optional AnimationTimeline? timeline,
              optional any options)]
interface WorkletAnimation : Animation {
        readonly attribute DOMString animatorName;
};


[Exposed=AnimationWorklet]
interface WorkletGroupEffect {
  sequence<AnimationEffect> getChildren();
};

[Exposed=AnimationWorklet]
partial interface AnimationEffect {
    // Intended for use inside Animation Worklet scope to drive the effect.
    attribute double localTime;
};

Issues Index

Consider giving user agents permission to skip running animator instances to throttle slow animators.
should be explicit as to what happens if the animateFunction throws an exception. At least we should have wording that the localTime values of the keyframes are ignored to avoid incorrect partial updates.
Come with appropriate mechanism’s for animator instance to get notified when its animation currentTime is changing e.g., via reverse(), finish() or playbackRate change. So that it can react appropriately. <https://github.com/w3c/css-houdini-drafts/issues/811>
The above interface exposes a conservative subset of GroupEffect proposed as part of web-animation-2. We should instead move this into a delta spec against the web-animation. <https://github.com/w3c/csswg-drafts/issues/2071>