<style type="text/css">
  table.event-state-transitions {
    width: 100%;
    border-spacing: 0px;
    border-collapse: collapse;
  }
  table.event-state-transitions th:first-child {
    width: 30%;
  }
  table.event-state-transitions th {
    text-align: center;
  }
  table.event-state-transitions td {
    padding: 0.2em 1em;
    border: 1px solid black;
  }
</style>

<pre class='metadata'>
Title: CSS Animations Module Level 2
Status: ED
Work Status: Exploring
Shortname: css-animations
Level: 2
Group: csswg
ED: https://drafts.csswg.org/css-animations-2/
TR: https://www.w3.org/TR/css-animations-2/
Previous Version: https://www.w3.org/TR/2023/WD-css-animations-2-20230602/
Editor: L. David Baron, Google https://www.google.com/, https://dbaron.org/, w3cid 15393
Editor: Brian Birtles, Invited Expert, brian@birchill.co.jp, w3cid 43194
!Issues List: https://github.com/w3c/csswg-drafts/labels/css-animations-2
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
</pre>
<!-- !Issues List: <a href="https://www.w3.org/Bugs/Public/buglist.cgi?component=Animations&list_id=36653&product=CSS&query_format=advanced&resolution=---">In Bugzilla</a> -->
<pre class=anchors>
urlPrefix: https://dom.spec.whatwg.org/; type: dfn; spec: dom
    text: event target
</pre>
<pre class=link-defaults>
spec:cssom-1; type:dfn;
    text:property name; for:CSS declaration
spec:web-animations-1; type:dfn;
    text:active duration
    text:active phase; for:animation effect
    text:active time
    text:after phase; for:animation effect
    text:animation class
    text:animation effect
    text:animation playback events
    text:associated effect
    text:associated effect end
    text:before phase; for:animation effect
    text:current iteration
    text:current time; for:animation
    text:composite operation
    text:fill mode
    text:idle play state
    text:idle phase; for:animation effect
    text:iteration duration
    text:iteration count
    text:iteration start
    text:keyframe
    text:pause an animation
    text:paused play state
    text:pending pause task
    text:pending play task
    text:play an animation
    text:play state
    text:playback direction
    text:start delay
    text:end delay
    text:target element
    text:unresolved
spec:web-animations-2; type:dfn;
    text:active interval; for:animation trigger
    text:default range
    text:exit range
spec:scroll-animations-1; type:dfn;
    text:animation-range-start
    text:animation-range-end
spec:css-animations-1; type:value; 
    text:running
    text:paused
</pre>

<h2 id="delta">Delta specification</h2>

<p>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.</p>

# Animations # {#animations}

Changes to any of the animation properties defined in this specification
cause the corresponding {{CSSAnimation}} object and its associated objects
to be updated according to the correspondence between these properties
and Web Animations concepts defined in [[#keyframes]].

However, if the author modifies the animation
using the Web Animations programming interface,
the changes from the programming interface take precedence as follows:

*   After a successful call to {{KeyframeEffect/setKeyframes()}}
    on the {{KeyframeEffect}} associated with a {{CSSAnimation}},
    any subsequent change to matching ''@keyframes'' rules or the resolved value
    of the 'animation-timing-function' property for the target element
    will not be reflected in that animation.

    However, if the last matching ''@keyframes'' rule is removed
    the animation must still be canceled.

*   After a successful call to {{AnimationEffect/updateTiming()}}
    on the {{KeyframeEffect}} associated with a {{CSSAnimation}},
    for each property included in the
    {{AnimationEffect/updateTiming(timing)/timing}} parameter,
    any subsequent change to a corresponding animation property
    will not be reflected in that animation.

    For example, calling
    <code>cssAnimation.effect.updateTiming({ duration: 1000 })</code>
    would cause subsequent changes to 'animation-duration' to be ignored
    whilst changes to 'animation-delay' would still be reflected
    in the {{KeyframeEffect}}'s timing.

*   After a successful call to {{Animation/play()}} or {{Animation/pause()}}
    on a {{CSSAnimation}},
    any subsequent change to the 'animation-play-state' will no longer
    cause the {{CSSAnimation}} to be played or paused
    as defined in [[#animation-play-state]].

*   After a successful call to {{Animation/reverse()}} on a {{CSSAnimation}}
    or after successfully setting the {{Animation/startTime}}
    on a {{CSSAnimation}},
    if, as a result of that call the [=play state=] of the
    {{CSSAnimation}} changes to or from the [=play state/paused=] play state,
    any subsequent change to the 'animation-play-state' will no longer
    cause the {{CSSAnimation}} to be played or paused
    as defined in [[#animation-play-state]].

    The requirement for a change to or from the [=play state/paused=] state
    ensures that even after calling
    {{Animation/reverse()}} or setting the {{Animation/startTime}}
    on a running animation,
    the animation continues to observe changes in 'animation-play-state'.

*   After successfully setting the {{Animation/effect}} of a {{CSSAnimation}}
    to <code>null</code>
    or some {{AnimationEffect}} other than the original {{KeyframeEffect}},
    all subsequent changes to animation properties other than
    'animation-name', 'animation-play-state', or 'animation-timeline'
    will not be reflected in that animation.
    Similarly, any change to matching ''@keyframes'' rules will not be reflected
    in that animation.
    However, if the last matching ''@keyframes'' rule is removed
    the animation must still be canceled.

Note, the reference to a successful call in the above rules
is necessary to ensure that
when an exception is thrown by any of these methods,
the override behavior is <em>not</em> applied.

## Owning element ## {#owning-element-section}

The <dfn>owning element</dfn> of an animation refers to the element or
pseudo-element to which the 'animation-name' property was applied that generated
the animation.

If the 'display' property of an element is set to ''display/none''
and its 'display' value would compute to ''display/none'' when ignoring the Transitions and Animations [=cascade origins=],
then terminate running animations with this <a>owning element</a>.
If an element has a 'display' of ''display/none'' and
its 'display' value had computed to ''display/none'' when ignoring the Transitions and Animations [=cascade origins=],
updating 'display' to a value other than ''display/none''
will start all animations applied to the element by the 'animation-name' property.

Note: In practice, this means that an animation to a 'display' value of ''display/none'' will not terminate running animations
unless the style also computes to ''display/none'' without the effect of the animations.

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 <a>owning element</a>, the animation is
disassociated from its <a>owning element</a> (that is, it has no <a>owning
element</a> from that point forwards).

<div class="note">

In the example below, <code>animation</code>'s initial <a>owning element</a>
is <code>elem</code>. <code>animation</code> is disassociated from
<code>element</code> through an update to the computed value of
<code>elem</code>'s 'animation-name' property.

<pre class="example lang-javascript">
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 element
</pre>

Note that although the <a>owning element</a> is often equal to the
[=target element=] of an animation's [=associated effect=],
this is not always the case.
The following example demonstrates some of the situations where these two
elements may differ.

<pre class="example lang-javascript">
elem.style.animation = 'move 1s';
let animation = elem.getAnimations()[0];
// animation.effect.target == elem == animation's owning element

animation.effect.target = elem2;
// animation.effect.target == elem2 != animation's owning element

animation.effect = null;
// animation.effect?.target is undefined != animation's owning element
</pre>

</div>

## Animation composite order ## {#animation-composite-order}

[=Animations=] generated from the markup defined in
this specification have an <a>animation class</a> of &lsquo;CSS
Animation&rsquo;.

CSS Animations <em>with</em> an <a>owning element</a> have a <em>later</em>
composite order than CSS Transitions but an <em>earlier</em> composite order
than animations without a specific <a>animation class</a>.

Within the set of CSS Animations <em>with</em> an <a>owning element</a>, two
animations <var>A</var> and <var>B</var> are sorted in composite order (first to
last) as follows:

1.  If the <a>owning element</a> of <var>A</var> and <var>B</var>
    differs, sort <var>A</var> and <var>B</var> by <a>tree order</a>
    of their corresponding <a>owning elements</a>.
    With regard to pseudo-elements, the sort order is as follows:

    *   element
    *   ::marker
    *   ::before
    *   any other pseudo-elements not mentioned specifically in this list,
        sorted in ascending order by the Unicode codepoints that make up each selector
    *   ::after
    *   element children

1.  Otherwise, sort <var>A</var> and <var>B</var> based on their position in the
    computed value of the 'animation-name' property of the (common) <a>owning
    element</a>.

When determining the composite order in order
to sort [[#events|animation events]]
where either or both of the events is an {{animationcancel}} event,
treat the CSS Animation(s) for which the {{animationcancel}} event was generated
as having an [=owning element=] corresponding to
the owning element in use at the moment when the CSS Animation was cancelled.
Furthermore,
use the position of the animation in the 'animation-name' property
in effect at the time when the CSS Animation was cancelled
sorting such that positions of cancelled animations sort
before positions of animations that have not been cancelled.

The composite order of CSS Animations <em>without</em> an <a>owning element</a>
is based on their position in the <a>global animation list</a>.

Issue: This differs from the behavior defined for transitions. We should
probably sort transitions first, then animation, then use the global animation
list. The reason being that when developer tools etc. hang on to orphaned
animations and transitions in order to replay them, they should maintain
roughly the same composite order.

CSS Animations generated using the markup defined in this specification are
<em>not</em> added to the <a>global animation list</a> when they are created.
Instead, these animations are appended to the <a>global animation list</a> at
the first moment when they transition out of the [=play state/idle=] play state
after being disassociated from their <a>owning element</a>.
CSS Animations that have been disassociated from their <a>owning element</a>
but are still [=play state/idle=] do not have a defined composite order.

Note, this behavior relies on the fact that disassociating an animation
from its <a>owning element</a> always causes it to enter (or remain) in the
[=play state/idle=] play state.

<h2 id="keyframes">
Assembling Keyframes</h2>

<h3 id="keyframe-rules">
Declaring Keyframes: the ''@keyframes'' rule</h3>

See [[css-animations-1#keyframes]].

<h3 id="keyframe-processing">
Processing Keyframes</h3>

For each animation effect defined by the <var ignore=''>N</var>th item
in the [=coordinated value list=] of the 'animation-*' properties
on target (pseudo-)element |element|,
its associated [=keyframes=] are generated as follows:

1.  <strong>Set Defaults:</strong>

    *   Let |default timing function| be the corresponding [=computed value=]
        of 'animation-timing-function' on |element|.

    *   Let |default composite| be the corresponding [=computed value=]
        of 'animation-composition' on |element|.

    *   Let |keyframes| be an empty sequence of [=keyframe=] objects,
        each possessing a
        |keyframe offset|,
        |keyframe timing function|,
        |keyframe composite|,
        and |keyframe values|.

    *   Let |animated properties| be an empty set of CSS [=property names=].

1.  <strong>Collect Declared Keyframes:</strong>
    1.  Find the last ''@keyframes'' at-rule in document order
        with <<keyframes-name>> matching
        the corresponding 'animation-name' value |name|.

        If there is no ''@keyframes'' at-rule
        with <<keyframes-name>> matching |name|
        (or if |name| is ''animation-name/none''),
        abort this procedure.
        In this case no animation is generated,
        and any existing animation matching |name| is canceled.

    1.  Group together all <<keyframe-block>> declarations
        that share the same [=specified value|specified=] <<keyframe-selector>>
        (treating ''@keyframe/from'' as ''0%'' and ''@keyframe/to'' as ''100%''),
        last declared 'animation-timing-function' [=computed value=]
        (defaulting to |default timing function| if there is no such declaration),
        and last declared 'animation-composition' [=computed value=]
        (defaulting to |default composite| if there is no such declaration).

    1.  For each such group of matching <<keyframe-block>> declarations,
        ordered by their earliest <<keyframe-block>> in the sorted order:

            1.  [=Cascade=] together all of its [=declaration blocks=]
                such that for each CSS property
                (except those that are “not animatable”, which must be ignored)
                the last declaration among all its <<keyframe-block>> declarations
                takes precedence.
                [[CSS-CASCADE-4]]

                Note: The [=cascade=] will
                expand [=shorthand properties=] into their [=sub-properties=]
                and map together corresponding property pairs in each [=logical property group=]
                according to the |element|’s [=computed value|computed=] [=writing mode=].

            1.  Append to |keyframes| a new empty [=keyframe=]
                with the group’s |keyframe offset|,
                |keyframe timing function|,
                and |keyframe composite|.
                Give its |keyframe values|
                the set of [=declared values=] resulting from this cascade.

            1.  Add each [=property name=] that was added to its {{CSSKeyframesRule/cssRules}}
                to |animated properties|.

1.  <strong>Generate Initial and Final Frames:</strong>

    1.  Find or create the |initial keyframe|,
        a [=keyframe=] with a |keyframe offset| of ''0%'',
        |default timing function| as its |keyframe timing function|,
        and |default composite| as its |keyframe composite|.

    1.  For any property in |animated properties|
        that is not otherwise present in a keyframe with an offset of ''0%''
        or one that would be positioned earlier in the [=used keyframe order=],
        add the [=computed value=] of that property on |element|
        to |initial keyframe|’s |keyframe values|.

    1.  If |initial keyframe|’s |keyframe values| is not empty,
        prepend |initial keyframe| to |keyframes|.

    1.  Repeat for |final keyframe|,
        using an offset of ''100%'',
        considering keyframes positioned <em>later</em> in the [=used keyframe order=],
        and <em>appending</em> to |keyframes|.

1.  <strong>Sort Frames:</strong>

    *   The <dfn lt="specified keyframe order">specified order</dfn> of |keyframes|
        is the order resulting from the steps above,
        i.e. document order with duplicate keyframes collapsed
        to the earliest position.

    *   The <dfn lt="computed keyframe order">computed order</dfn> of |keyframes|--
        which is the order returned by {{KeyframeEffect/getKeyframes()}}--
        is found by shifting any keyframes whose offset was specified as
        a <<percentage>>, ''@keyframes/from'' keyword, or ''@keyframes/to'' keyword
        to the front of the list (after the generated |initial keyframe|, if any),
        and performing a stable sort on these keyframes
        by their |keyframe offset|s.

    *   The <dfn lt="used keyframe order">used order</dfn> of |keyframes|--
        which is the order used to interpolate and compute the actual animation frames--
        is found by attaching the |keyframes|
        onto the animation effect’s timeline
        assuming an [=iteration count=] of 1
        and ordering them from earliest to latest,
        breaking ties by using the [=computed keyframe order=].

    Issue: Any specific requirements on sorting computed keyframes introduced by
    this spec should be integrated into
    [[web-animations-1#calculating-computed-keyframes]].
    Any specific requirements on used keyframes introduced by this spec
    should be integrated into
    [[web-animations-1#the-effect-value-of-a-keyframe-animation-effect]].
    The above description of the distinction between these sets of keyframes
    should be moved to an informative note.

    Note: Although the [=computed keyframe order=]
    sorts keyframes with <<percentage>> offsets,
    it maintains keyframes specified with a <<timeline-range-name>>
    in their [=specified keyframe order=]--
    after any <<percentage>> keyframes
    (other than a generated |final keyframe|),
    even if these come later in the [=used keyframe order=].

<h2 id="animation-definition">
Declaring Animations</h2>

    CSS Animations are defined by binding keyframes to an element
    using the 'animation-*' properties.
    These list-valued properties,
    which are all [=longhands=] of the 'animation' [=shorthand=],
    form a [=coordinating list property group=]
    with 'animation-name' as the [=coordinating list base property=]
    and each item in the [=coordinated value list=]
    defining the properties of a single animation effect.

    See [[css-values-4#linked-properties]]
    for how the individual 'animation-*' property values coordinate.

## The 'animation-duration' property ## {#animation-duration}

  <pre class='propdef'>
  Name: animation-duration
  Value: [ auto | <<time [0s,∞]>> ]#
  Initial: auto
  Applies to: all elements
  Inherited: no
  Percentages: N/A
  Computed value: list, each item either a time or the keyword ''animation-duration/auto''
  Animation type: not animatable
  Canonical order: per grammar
  </pre>

  The 'animation-duration' property specifies the [=iteration duration=]
  of the animation's associated [=animation effect=].

  <dl dfn-for=animation-duration dfn-type=value>
    <dt><dfn>auto</dfn>
    <dd>
      For time-driven animations,
      equivalent to ''0s''.

      For [=scroll-driven animations=],
      equivalent to the duration necessary to fill the timeline
      in consideration of 'animation-range', 'animation-delay', and 'animation-iteration-count'.
      See [[scroll-animations-1#finite-attachment]].

    <dt><dfn><<time [0s,∞]>></dfn>
    <dd>
      For time-driven animations,
      specifies the length of time that an animation takes to complete one cycle.
      A negative <<time>> is invalid.

      For [=scroll-driven animations=],
      treated as ''animation-duration/auto''.
  </dl>

  If the [=used value|used=] 'animation-duration' is ''0s'',
  the animation itself still occurs (instantaneously).
  The animation’s start and end events are still fired.
  If 'animation-fill-mode' is set to ''single-animation-fill-mode/backwards'' or ''single-animation-fill-mode/both'',
  the first frame of the animation
  (as defined by 'animation-direction')
  will be displayed during the 'animation-delay';
  and if 'animation-fill-mode' is set to ''single-animation-fill-mode/forwards'' or ''single-animation-fill-mode/both'',
  the last frame of the animation
  (as defined by 'animation-direction')
  will be displayed after the 'animation-delay'.
  However, if 'animation-fill-mode' is set to ''animation-fill-mode/none''
  the keyframes of the animation animation will have no noticeable effect.

  For backwards-compatibility with Level 1,
  when the [=computed value=] of 'animation-timeline' is ''animation-timeline/auto''
  (i.e. only one list value, and that value being ''animation-timeline/auto''),
  the [=resolved value=] of ''animation-duration/auto'' for 'animation-duration'
  is ''0s'' whenever its [=used value=] would also be ''0s''.

## The 'animation-timing-function' property ## {#animation-timing-function}

The 'animation-timing-function' is used to determine the [=timing function=]
applied to each [=keyframe=] as defined in [[#keyframes]].

## The 'animation-iteration-count' property ## {#animation-iteration-count}

The 'animation-iteration-count' property specifies the [=iteration count=]
of the animation's associated [=animation effect=].

## The 'animation-direction' property ## {#animation-direction}

The 'animation-direction' property specifies the [=playback direction=]
of the animation's associated [=animation effect=].

## The 'animation-play-state' property ## {#animation-play-state}

The 'animation-play-state' is used to pause or play the animation.

If at any time,
including when the animation is first generated,
the resolved value of 'animation-play-state'
corresponding to an animation is newly ''running'',
the implementation must run the procedure to [=play an animation=]
for the given animation
with the <var ignore>auto-rewind flag</var> set to false.

If at any time,
including when the animation is first generated,
the resolved value of 'animation-play-state'
corresponding to an animation is newly ''paused'',
the implementation must run the procedure to [=pause an animation=]
for the given animation.

The above requirements do not apply
if the animation's play state is being overridden by the Web Animations API
as described in [[#animations]].

## The 'animation-delay-start' property ## {#animation-delay-start}

  The 'animation-delay-start' property specifies the [=start delay=] of the
  animation's associated [=animation effect=], which
  defines when the animation will start. It allows an animation
  to begin execution some time after it is applied,
  or to appear to have begun execution some time <em>before</em> it is applied.

  <pre class='propdef'>
  Name: animation-delay-start
  Value: <<time>>#
  Initial: 0s
  Applies to: all elements
  Inherited: no
  Animation type: not animatable
  Percentages: N/A
  Computed value: list, each item a duration
  Canonical order: per grammar
  </pre>

  <dl>
    <dt><dfn value for=animation-delay-start><<time>></dfn>
    <dd>
      The <<time>> defines how long of a delay there is between the start of the animation
      (when the animation is applied to the element via these properties)
      and when it begins executing.
      A delay of ''0s'' (the initial value) means that the animation will execute as soon as it is applied.

      A negative delay is <strong>valid</strong>.
      Similar to a delay of ''0s'', it means that the animation executes immediately,
      but is automatically progressed by the absolute value of the delay,
      as if the animation had started the specified time in the past,
      and so it appears to start partway through its [=active duration=].
      If an animation's keyframes have an implied starting value,
      the values are taken from the time the animation starts,
      not some time in the past.
  </dl>

## The 'animation-delay-end' property ## {#animation-delay-end}

  The 'animation-delay-end' property specifies the [=end delay=] of the
  animation's associated [=animation effect=], which
  defines when the animation will start when it is reversed.

  <pre class='propdef'>
  Name: animation-delay-end
  Value: <<time [0s,∞]>>#
  Initial: 0s
  Applies to: all elements
  Inherited: no
  Animation type: not animatable
  Percentages: N/A
  Computed value: list, each item a duration
  Canonical order: per grammar
  </pre>

  Issue: Should animation-delay-end support negative values? If so, what would it mean?

  Issue: Should animation-delay-end be added to the animation shorthand?

## The 'animation-delay' shorthand ## {#animation-delay}

  <pre class="propdef shorthand">
    Name: animation-delay
    Value: [ <<'animation-delay-start'>> <<'animation-delay-end'>>? ]#
  </pre>

  The 'animation-delay' property is a [=shorthand property|shorthand=]
  that sets 'animation-delay-start' and 'animation-delay-end'
  together in a single declaration. Specifying a single value will
  set the 'animation-delay-start' to that value, and will not affect
  the  value of 'animation-delay-end', for backward compatibility with
  the 'animation-delay' previous longhand behavior.

## The 'animation-fill-mode' property ## {#animation-fill-mode}

The 'animation-fill-mode' property specifies the [=fill mode=]
of the animation's associated [=animation effect=].

## The 'animation-composition' property ## {#animation-composition}

The 'animation-composition' property defines the <a>composite operation</a>
used when multiple animations affect the same property simultaneously.

<pre class='propdef'>
Name: animation-composition
Value: <<single-animation-composition>>#
Initial: replace
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: list, each item a keyword as specified
Animation type: not animatable
Canonical order: per grammar
</pre>

<span class=prod><dfn type>&lt;single-animation-composition></dfn> = replace | add | accumulate</span>

The values of 'animation-composition' have the meaning defined for the
corresponding values of the <a>composite operation</a> 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.

<div class='example'>
  For example, the following stylesheet defines two different animations
  targeting the 'scale' property.

  <pre>
    @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;
    }
  </pre>

  If these two animations are applied to the same element, normally only
  one animation would apply, but by specifying ''animation-composition/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.

  <pre>
    .icon {
      filter: blur(20px);
      transition: filter 0.5s;
    }
    .icon:hover {
      filter: blur(0px);
      animation: brightness-pulse 3s infinite add;
    }

    @keyframes brightness-pulse {
      0% {
        scale: 1.1;
        filter: brightness(130%);
      }
      10% {
        scale: 1;
        filter: brightness(100%);
      }
    }
  </pre>

  Issue: Create pictures of these examples and verify they make sense.
</div>


## The 'animation-timeline' property ## {#animation-timeline}

The 'animation-timeline' property defines the <a>timeline</a> used with the
animation.

Note: This specification does not introduce any syntax to specify animation
timelines but instead it is up to others specifications such as Scroll-linked
Animations [[SCROLL-ANIMATIONS]] to do so.

<pre class='propdef'>
Name: animation-timeline
Value: <<single-animation-timeline>>#
Initial: auto
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: list, each item either
    the keyword ''single-animation-timeline/none'',
    the keyword ''single-animation-timeline/auto'',
    a case-sensitive [=css identifier=],
    a computed ''scroll()'' function,
    or
    a computed ''view()'' function
Canonical order: per grammar
Animation Type: not animatable
</pre>

<pre class=prod>
<dfn type>&lt;single-animation-timeline></dfn> = auto | none | <<dashed-ident>> | <<scroll()>> | <<view()>>
</pre>

The 'animation-timeline' property is similar to properties like 'animation-name'
and 'animation-duration' in that it can have one or more values, each one
imparting additional behavior to a corresponding [=animation=] on the element,
with the timelines matched up with animations as described
[[css-animations-1#animation-name|here]].

Each value has type <<single-animation-timeline>>, whose possible values have
the following effects:

<dl dfn-for="animation-timeline,<single-animation-timeline>" dfn-type=value>
:   <dfn>auto</dfn>
::  The animation's [=timeline=] is a {{DocumentTimeline}}, more specifically
    the <a>default document timeline</a>.

:   <dfn>none</dfn>
::  The animation is not associated with a [=timeline=].

:   <dfn><<dashed-ident>></dfn>
::  If a named [=scroll progress timeline=] or [=view progress timeline=]
    is in scope on this element,
    use the referenced timeline
    as defined in [[scroll-animations-1#timeline-scope]].

    Otherwise the animation is not associated with a [=timeline=].

:   <dfn><<scroll()>></dfn>
::  Use the [=scroll progress timeline=] indicated by the given ''scroll()'' function.
    See [[scroll-animations-1#scroll-notation]].

:   <dfn><<view()>></dfn>
::  Use the [=view progress timeline=] indicated by the given ''view()'' function.
    See [[scroll-animations-1#view-notation]].
    </dl>


Issue: Make it easier to use 'animation-name' to select the timeline when
'animation-timeline' is not specified. Allowing 'animation-name' to be used for
selecting timeline enables most common animations to have to use a single name
for both their keyframes and timeline which is simple and ergonomics. The
'animation-timeline' property gives authors additional control to independently
select keyframes and timeline if necessary.

When multiple 'animation-*' properties are set simultaneously,
'animation-timeline' is updated first,
so e.g. a change to 'animation-play-state' applies
to the simultaneously-applied timeline specified in 'animation-timeline'.


## The 'animation' shorthand property ## {#animation-shorthand}

The 'animation' shorthand property syntax is as follows:

<span class=prod><dfn type>&lt;single-animation></dfn> = <<'animation-duration'>> || <<easing-function>> || <<'animation-delay-start'>> || <<single-animation-iteration-count>> || <<single-animation-direction>> || <<single-animation-fill-mode>> || <<single-animation-play-state>> || [ none | <<keyframes-name>> ] || <<single-animation-timeline>></span>


<!-- Big Text: events

█████▌ █▌   █▌ █████▌ █    █▌ █████▌  ███▌
█▌     █▌   █▌ █▌     █▌   █▌   █▌   █▌  █▌
█▌     █▌   █▌ █▌     ██▌  █▌   █▌   █▌
████   ▐▌   █  ████   █▌▐█ █▌   █▌    ███▌
█▌      █  ▐▌  █▌     █▌  ██▌   █▌       █▌
█▌      ▐▌ █   █▌     █▌   █▌   █▌   █▌  █▌
█████▌   ▐█    █████▌ █▌   ▐▌   █▌    ███▌
-->

# Animation Events # {#events}

## Event dispatch ## {#event-dispatch}

Note, this is a more general description of event dispatch than that of CSS
Animations Level 1 [[CSS3-ANIMATIONS]] since it must account for the
possibility of animations being seeked or reversed using the Web Animations API
[[WEB-ANIMATIONS]].

The [=event target|target=] for a CSS animation event is
the animation's [=owning element=].
If there is no [=owning element=], no CSS animation events are dispatched
(although the [=animation playback events=] defined in Web Animations are still
dispatched at the corresponding {{CSSAnimation}} object).

For the purpose of determining which events to dispatch, the
[[web-animations-1#animation-effect-phases-and-states|phases]] defined in
the Web Animations model are used. These definitions apply to an <a>animation
effect</a>, however, for the purpose of dispatching events, we consider a
CSS Animation to have the same phase as its [=associated effect=].
For example, a CSS Animation is in the [=animation effect/before phase=] if its
[=associated effect=] is in the [=animation effect/before phase=].

A CSS Animation that does not have an [=associated effect=]
is considered to be in the <a>idle phase</a>
if its [=animation/current time=] is <a>unresolved</a>, in the
[=animation effect/before phase=] if its <a>current time</a> is less than zero,
and in the [=animation effect/after phase=] otherwise.

Similarly, subsequent references to the <a>start delay</a>, <a>active
duration</a>, <a>current iteration</a>, <a>iteration start</a>, and
<a>iteration duration</a> of a CSS animation should be understood to refer
to the corresponding properties of the animation's [=associated effect=].

For calculating the {{AnimationEvent/elapsedTime}} of each event, the following
definitions are used:

*   <dfn>interval start</dfn> =
    <code>max(min(-<a>start delay</a>, <a>active duration</a>), 0)</code>
*   <dfn>interval end</dfn> =
    <code>max(min([=associated effect end=] - <a>start delay</a>,
                  <a>active duration</a>), 0)</code>

Each time a new [=animation frame=] is established and the animation does
<em>not</em> have a [=pending play task=] or [=pending pause task=],
the events to dispatch are determined by
comparing the animation's phase before and after establishing the new
[=animation frame=] as follows:

<table class="event-state-transitions">
  <thead>
    <tr>
      <th>Change</th>
      <th>Events dispatched</th>
      <th><dfn>Elapsed time</dfn> (ms)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>[=animation effect/idle phase|idle=] or
          [=animation effect/before phase|before=] &rarr;
          [=animation effect/active phase|active=]</td>
      <td>{{animationstart}}</td>
      <td><a>interval start</a>
      </td>
    </tr>
    <tr>
      <td rowspan="2">
        [=animation effect/idle phase|idle=] or
        [=animation effect/before phase|before=] &rarr;
        [=animation effect/after phase|after=] <a
        href="#multiple-events-note">&#x66d;</a></td>
      <td>{{animationstart}}</td>
      <td><a>interval start</a>
      </td>
    </tr>
    <tr>
      <td>{{animationend}}</td>
      <td><a>interval end</a>
      </td>
    </tr>
    <tr>
      <td>[=animation effect/active phase|active=] &rarr;
          [=animation effect/before phase|before=]</td>
      <td>{{animationend}}</td>
      <td><a>interval start</a></td>
    </tr>
    <tr>
      <td>[=animation effect/active phase|active=] &rarr;
          [=animation effect/active phase|active=]
          <em>and</em>
          the <a>current iteration</a> of the animation's [=associated effect=]
          has changed since the previous animation frame
      </td>
      <td>{{animationiteration}}</td>
      <td>(See below)
          <a href="#animation-iteration-elapsed-time">&dagger;</a></td>
    </tr>
    <tr>
      <td>[=animation effect/active phase|active=] &rarr;
          [=animation effect/after phase|after=]</td>
      <td>{{animationend}}</td>
      <td><a>interval end</a></td>
    </tr>
    <tr>
      <td>[=animation effect/after phase|after=] &rarr;
          [=animation effect/active phase|active=]</td>
      <td>{{animationstart}}</td>
      <td><a>interval end</a></td>
    </tr>
    <tr>
      <td rowspan="2">[=animation effect/after phase|after=] &rarr;
                      [=animation effect/before phase|before=] <a
                      href="#multiple-events-note">&#x66d;</a></td>
      <td>{{animationstart}}</td>
      <td><a>interval end</a></td>
    </tr>
    <tr>
      <td>{{animationend}}</td>
      <td><a>interval start</a></td>
    </tr>
    <tr>
      <td><em>not</em> [=animation effect/idle phase|idle=] and <em>not</em>
          [=animation effect/after phase|after=] &rarr;
          [=animation effect/idle phase|idle=]</td>
      <td>{{animationcancel}}</td>
      <td>The <a>active time</a> of the animation at the moment it was cancelled
          calculated using a <a>fill mode</a> of both.</td>
    </tr>
  </tbody>
</table>

<p id="multiple-events-note">&#x66d; Where multiple events are listed for
a state change, all events are dispatched in the order listed and in immediate
succession.</p>

<p id="animation-iteration-elapsed-time">&dagger; The <a>elapsed time</a> for
an {{animationiteration}} event is defined as follows:</p>

1.  Let <var>previous current iteration</var> be the <a>current iteration</a>
    from the previous animation frame.

1.  If <var>previous current iteration</var> is greater than <a>current
    iteration</a>, let <var>iteration boundary</var> be <code><a>current
    iteration</a> + 1</code>, otherwise let it be <a>current iteration</a>.

1.  The <a>elapsed time</a> is the result of evaluating
    <code>(<var>iteration boundary</var> - <a>iteration start</a>) &times;
    <a>iteration duration</a>)</code>.

Since the <a>elapsed time</a> 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}}.

## The <code>AnimationEvent</code> Interface ## {#interface-animationevent}

### IDL Definition ### {#interface-animationevent-idl}

Add {{AnimationEvent/animation}} to the {{AnimationEvent}} interface and {{AnimationEventInit}} dictionary as follows:

<pre class="idl">
[Exposed=Window]
partial interface AnimationEvent {
  readonly attribute CSSAnimation? animation;
};

partial dictionary AnimationEventInit {
  CSSAnimation? animation = null;
};
</pre>

### Attributes ### {#interface-animationevent-attributes}

Add attribute descriptions as follows:

<dl dfn-type=attribute dfn-for=AnimationEvent>
  <dt><dfn>animation</dfn>
  <dd>
    The CSS Animation that fired the event.
</dl>

# DOM Interfaces # {#interface-dom}

## The CSSAnimation interface ## {#the-CSSAnimation-interface}

<pre class="idl">
[Exposed=Window]
interface CSSAnimation : Animation {
  readonly attribute CSSOMString animationName;
};
</pre>

:   <dfn attribute for=CSSAnimation>animationName</dfn>
::  The key used to find matching keyframes rules that define the
    [=associated 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.

## Requirements on pending style changes ## {#requirements-on-pending-style-changes}

Various operations may affect the <a lt="computed value">computed values</a> of
properties on elements. User agents may, as an optimization, defer recomputing
these values until it becomes necessary.
However, all operations included in programming interface defined in this
specification, as well as those operations defined in Web Animations
[[!WEB-ANIMATIONS]] that may return objects or animation state defined by this
specification, must produce a result consistent with having fully processed
any such pending changes to computed values.

<div class="note">
As an example, in the following code fragment, when the specified style of
<code>elem</code> is initially updated, a user agent may defer recalculating
the computed value of the 'animation' property.

However, the {{Animatable/getAnimations()}} method called on <code>elem</code>
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 <code>elem</code>'s 'animation' property and
create the requested {{CSSAnimation}} object before returning its result.

<div><pre class="example lang-javascript">
elem.style.animation = 'fadeOut 1s';
elem.getAnimations()[0].pause();
</pre></div>

Similarly, reading {{Animation/playState}} may depend on pending style
changes.

<div><pre class="example lang-javascript">
elem.style.animation = 'fadeOut 1s paused';
const anim = elem.getAnimations()[0];
elem.style.animationPlayState = 'running';
console.log(anim.playState); // Should be 'running'.
</pre></div>

</div>

<h2 id="priv">
  Privacy Considerations</h2>

  No privacy concerns have been reported on this specification.

  <h2 id="sec">
  Security Considerations</h2>

  No security concerns have been reported on this specification.

<h2 id="changes">Changes</h2>

<h3 id="changes-recent">Recent Changes</h3>

<p>Changes since the <a href="https://www.w3.org/TR/2023/WD-css-animations-2-20230602/">2 June 2023 Working Draft</a>:</p>

<ul>
  <!-- to 3 March 2026 -->
  <li>Moved the animation-trigger property to a new spec, animation-triggers-1
    (<a href="https://github.com/w3c/csswg-drafts/pull/13571">PR 13571</a>)
  </li>
  <li>Define trigger scope.  Flattened tree; removed anchor-scope reference
    (<a href="https://github.com/w3c/csswg-drafts/pull/13241">PR 13241</a>)
  </li>
  <li>Added play-once animation-action
    (<a href="https://github.com/w3c/csswg-drafts/issues/12611">Issue 12611</a>)
  </li>
  <li>Defined that event triggers can be defined to have enter/exit pairs, like timelines.</li>
  <li>Separated trigger concept from trigger instance</li>
  <li>Changed initial value of the exit ranges to auto, to match the start ranges
  </li>
  <li>Changed "animation-trigger-behavior" to "animation-trigger" and largely rewrote the definition
    (<a href="https://github.com/w3c/csswg-drafts/pull/13009">PR 13009</a>)
  </li>
  <li>Changed animation-trigger-type to animation-trigger-behavior
    (<a href="https://github.com/w3c/csswg-drafts/pull/12223">PR 12223</a>)
  </li>
  <li>Clarified that setting "effect" should not prevent the timeline to set "set" via animation-timeline
    (<a href="https://github.com/w3c/csswg-drafts/pull/11812">PR 11812</a>)
  </li>
  <li>Defined animation-trigger-* as reset-only sub-properties of animation
    (<a href="https://github.com/w3c/csswg-drafts/pull/11653#issue-2831268235">PR 11653</a>)
  </li>
  <li>Added note to Animation Frames about running the updating animation trigger state procedure</li>
  <li>Added algorithm for Setting a Trigger of an Animation</li>
  <li>Added the AnimationTrigger interface</li>
  <li>Moved all new definitions from web-animations-1 to web-animations-2</li>
  <li>Specified the animation-trigger property
    (<a href="https://github.com/w3c/csswg-drafts/issues/8942#issuecomment-1854342340">Issue 8942</a>)
  </li>
  <li>Defined order for sorting animationcancel events
    (<a href="https://github.com/w3c/csswg-drafts/issues/11064">Issue 11064</a>)
  </li>
  <li>Made animation-duration:auto resolve to 0s, for legacy compat
    (<a href="https://github.com/w3c/csswg-drafts/issues/6530">Issue 6530</a>)
  </li>
  <li>Switched timeline names from <<custom-ident>> to <<dashed-ident>>
    (<a href="https://github.com/w3c/csswg-drafts/issues/8746">Issue 8746</a>)
  </li>
</ul>

<p>Changes since the <a href="https://www.w3.org/TR/2023/WD-css-animations-2-20230302/">2 March 2023 Working Draft</a>:

<ul>
    <li>Added ''animation-duration/auto'' as the [=initial value=] of 'animation-duration'.
      (<a href="https://github.com/w3c/csswg-drafts/issues/6530">Issue 6530</a>)
    <li>Rewrote [[#keyframe-processing]]
      to re-use the [=cascade=],
      to handle non-percentage keyframe offsets,
      to handle keyframes with offsets outside the [0,1] range,
      and to use the value of 'animation-composition' as the default composite.
    <li>Reduced the cases where ''display: none'' cancel an animation.
      (<a href="https://github.com/w3c/csswg-drafts/issues/6429">Issue 6429</a>)
    <li>Cross-linked to [[css-values-4#linked-properties]] to define how the various 'animation-*' properties interact.
    <li>Clarified that among the animation properties, 'animation-timeline' is applied first.
</ul>

<h3 id="changes-level-1">Changes since CSS Animations, Level 1</h3>

<ul>
  <li>
    The interaction between CSS Animations and Web Animations is defined,
    and the concepts of the owning element and animation composite order
    are introduced.
  </li>
  <li>
    Generation of keyframe objects is described in detail.
  </li>
  <li>
    The 'animation-composition' property is introduced,
    which defines the composite operation used
    when multiple animations affect the same property simultaneously.
  </li>
  <li>
    The 'animation-timeline' property is introduced,
    which defines the timeline used with the animation.
  </li>
  <li>
    The 'animation' shorthand property is updated
    to account for these new properties.
  </li>
  <li>
    Dispatch of animation events is described.
  </li>
  <li>
    The {{CSSAnimation}} interface is added.
  </li>
  <li>
    Requirements on pending style changes are described.
  </li>
</ul>
