animation-trigger CSS property

Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.

The animation-trigger CSS property specifies whether CSS animations declared on an element are triggered animations or not, and if so, what their triggers are and how they should behave when the trigger becomes active or inactive. This can be used to create scroll-triggered animations.

Syntax

css
/* none keyword */
animation-trigger: none;

/* Dashed ident plus a single <animation-action> */
animation-trigger: --my-trigger play;
animation-trigger: --my-other-trigger play-once;

/* Dashed ident plus two <animation-action>s */
animation-trigger: --my-trigger play-forwards play-backwards;
animation-trigger: --my-other-trigger play reset;

/* Multiple animation-trigger values */
animation-trigger:
  none,
  --my-trigger play-forwards play-backwards,
  --my-other-trigger play reset;

/* Global values */
animation-trigger: inherit;
animation-trigger: initial;
animation-trigger: revert;
animation-trigger: revert-layer;
animation-trigger: unset;

The animation-trigger property may be specified using one or more animation-trigger values separated by commas. Each animation-trigger value consists of the keyword none, or a <dashed-ident> followed by one or more <animation-action> values.

Values

none

Specifies that the animation is not a triggered animation.

<dashed-ident>

An identifier equal to the timeline-trigger-name of the trigger that will trigger the animation.

<animation-action>

Specifies the behavior of the animation once the trigger is activated (in the case of the first value) and deactivated (in the case of the second, optional value).

Description

The animation-trigger property specifies which trigger will control an animated element's animations, turning them, for example, into CSS scroll-triggered animations. The trigger is identified via a <dashed-ident> value, which is defined in the tracked element's timeline-trigger-name property. If the <dashed-ident> specified inside the animation-trigger isn't set as a timeline-trigger-name on a suitable element inside the same document, the animation-trigger is ignored.

You can also include one or more <animation-action> keywords in an animation-trigger value, which specify the behavior of the animation once the trigger is activated and deactivated.

For example:

css
.animated {
  animation: rotate 3s infinite linear both;
  animation-trigger: --my-trigger play-forwards play-backwards;
}

In this case, the animation will be triggered by a trigger with a timeline-trigger-name of --my-trigger. Its <animation-action> keywords — play-forwards play-backwards — specify that the animation should play forwards on activation, and backwards on deactivation.

The trigger is a timeline specified by a timeline-trigger-source property set on an element whose position will be tracked again that timeline. It is most commonly a view progress timeline: When the scrollport that defines the timeline is scrolled such that the tracked element moves inside its activation range, the animation will play. When the tracked element reaches the end of the activation range, the animation will play backwards.

For example:

css
.trigger {
  timeline-trigger: --my-trigger view();
}

An element with this declaration set will have an identifying timeline-trigger-name of --my-trigger, and a timeline-trigger-source value of view(), which selects the nearest ancestor scrolling element to define its timeline trigger.

Note: The trigger can be defined using the timeline-trigger property, or its associated longhand properties — timeline-trigger-name, timeline-trigger-source, timeline-trigger-activation-range, and timeline-trigger-active-range.

Note: It is possible for the animated element and the element that creates the timeline to be the same element.

animation shorthand reset behavior

The animation-trigger property is a reset-only sub-property of the animation shorthand property. An animation-trigger value cannot be set via the animation shorthand; instead, animation resets animation-trigger to its initial value of none. For this reason, you should always set animation-trigger after a corresponding animation property in a declaration list.

Multiple scroll-triggered animations

The animation-trigger property works in the same way as the animation shorthand property and the other animation longhand properties with regards to setting multiple values:

  • If multiple animation-name values are set, but only a single animation-trigger value is set, the animation-trigger will apply to all the animations.
  • If two animation-trigger values are set, they will cycle between the animations until all of them have an animation-trigger value set.
  • And so on.

See Using CSS scroll-triggered animations > Multiple scroll-triggered animations for a working example.

Formal definition

Initial valuenone
Applies toall elements
Inheritedno
Computed valueas specified
Animation typeNot animatable

Formal syntax

animation-trigger = 
[ none | [ <dashed-ident> <animation-action>+ ]+ ]#

Examples

Basic usage

In this example, we show how to create a basic scroll-triggered animation.

HTML

Our markup contains two <div> elements, plus some basic text content to cause the page to scroll. We have hidden the text content for brevity.

html
<div class="animated">I am animated</div>

...

<div class="trigger">I create the trigger</div>

...

CSS

The .animated <div> element has an animation applied that rotates it. We set an animation-trigger value on it that references a timeline-trigger-name of --t; we also specify two <animation-action> values — play and pause — which specify that the animation will play on activation, and pause on deactivation.

The .trigger <div> element creates the animated <div>'s trigger using a timeline-trigger value of --t view(). This value includes the identifier referenced in the animated <div>'s animation-trigger property value (the timeline-trigger-name), associating the two together. It also includes a timeline-trigger-source value of view(), which sets the timeline trigger as a view progress timeline, and the element providing the timeline trigger as the nearest scrolling ancestor element.

css
div.animated {
  animation: rotate 3s infinite linear both;
  animation-trigger: --t play pause;
}

div.trigger {
  timeline-trigger: --t view();
}

Next, we give the animated <div> a position of fixed, positioning it near the top-left of the viewport so that we can easily see when its animation starts and stops.

css
div.animated {
  position: fixed;
  top: 25px;
  left: 25px;
}

Finally, we define the @keyframes for the rotate animation:

css
@keyframes rotate {
  from {
    rotate: 0deg;
  }

  to {
    rotate: 360deg;
  }
}

Result

The rendered result looks like this:

Try scrolling the content up. When any part of the .trigger <div> appears in the viewport, the animation will play; when it has completely left the viewport at either edge, the animation will pause.

Making the animated element create the trigger

In this example, we demonstrate how an animated element can also create its own trigger.

HTML

This time, our markup contains only a single <div> element, plus basic text content to cause the page to scroll. We have hidden all the markup for brevity.

CSS

The <div> element has an animation applied that smoothly inverts its colors. We set an animation-trigger value on it that references a timeline-trigger-name of --t; we also specify two <animation-action> values — play-forwards and play-backwards — which specify that the animation will play forwards on activation, and play in reverse on deactivation.

We then specify a timeline-trigger value of --t view() contain on the same <div>, meaning that it creates the trigger for its own animation. This value includes the identifier referenced in the animation-trigger property, plus:

  • A timeline-trigger-source value of view(), which sets the timeline trigger to the view progress timeline tracking the element inside its nearest scrolling ancestor element.

  • A timeline-trigger-activation-range value of contain, which means that the trigger will activate when the <div> is fully inside the viewport, and deactivate when it stops being fully inside the viewport.

    Note: This is in contrast to the default activation range, cover, which would cause the trigger to activate when any part of the <div> enters the viewport and deactivate only when it has fully left the viewport.

css
div {
  animation: invert-colors 0.6s ease-in both;
  animation-trigger: --t play-forwards play-backwards;
  timeline-trigger: --t view() contain;
}

Finally, we define the @keyframes for the invert-colors animation:

css
@keyframes invert-colors {
  from {
    background: orange;
    color: black;
  }

  to {
    background: black;
    color: orange;
  }
}

Result

The rendered result looks like this:

Try scrolling the content up. When the <div> fully appears in the viewport, its animation will play; when any part of the <div> leaves the viewport at either edge, the animation will play backwards.

Specifications

Specification
CSS Animations Level 2
# animation-trigger-prop

Browser compatibility

See also