timeline-trigger CSS property

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

The timeline-trigger CSS shorthand property defines a scroll-triggered animation trigger on an element.

Constituent properties

This property is a shorthand for the following CSS properties:

Syntax

css
/* Keyword */
timeline-trigger: none;

/* name | source */
timeline-trigger: --t view();
timeline-trigger: --t --my-timeline;

/* name | source | activation range */
timeline-trigger: --t view() contain;
timeline-trigger: --t view() entry exit 50%;

/* name | source | activation range | active range */
timeline-trigger: --t view() contain / cover;
timeline-trigger: --t view() entry / entry exit 50%;

/* Multiple triggers */
timeline-trigger:
  --t view(),
  --other-trigger --my-timeline entry / entry 50% exit 50%;

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

The timeline-trigger shorthand property is specified as the keyword none or one or more timeline triggers, separated by commas. Each timeline trigger is specified as a timeline-trigger-name value, a timeline-trigger-source and optionally, a timeline-trigger-activation-range value, separated by spaces.

If specified, the timeline-trigger-activation-range value can optionally be followed by a timeline-trigger-active-range value, with the two separated by a forward slash.

Values

none

Specifies that the element does not create a scroll-triggered animation trigger. Equivalent to none none normal.

<'timeline-trigger-name'>

A timeline-trigger-name value representing the trigger's identifying name. Defaults to none.

<'timeline-trigger-source'>

A timeline-trigger-source value representing the trigger's timeline. Defaults to auto.

<'timeline-trigger-activation-range'>

A timeline-trigger-activation-range value representing the trigger's activation range. Defaults to cover.

<'timeline-trigger-active-range'>

A timeline-trigger-active-range value representing the trigger's activation range. Defaults to the same value as the timeline-trigger-activation-range.

Note: Due to the potential for ambiguities in the syntax, this shorthand's values must be given in the order specified above.

Description

The timeline-trigger property can be used to set all the properties used to create a CSS scroll-triggered animation trigger in a single declaration.

For example:

css
.trigger {
  timeline-trigger: --my-trigger view() entry / entry exit 50%;
}

An element with this declaration set will have:

  • An identifying timeline-trigger-name of --my-trigger.
  • A timeline-trigger-source value of view(), which selects the element's nearest ancestor scrolling element to define its timeline trigger.
  • An activation range of entry, meaning that the trigger will activate when its tracked element starts to enter the viewport.
  • An active range of entry exit 50% meaning that once activated, the trigger will stay active until its tracked element leaves the range between the start of the entry range and 50% of the way through the exit range (when 50% of the tracked element has left the viewport).

An animated element can be triggered by the previously-described trigger by referencing its identifying name in its animation-trigger property.

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 controlled 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 when the trigger activates (when the tracked element is scrolled into the activation range), and backwards on deactivation (when the tracked element is scrolled out of the active range).

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

Formal definition

Initial valueas each of the properties of the shorthand:
Applies toall elements
Inheritedno
Computed valueas each of the properties of the shorthand:
Animation typeas each of the properties of the shorthand:

Formal syntax

timeline-trigger = 
none |
[ <'timeline-trigger-name'> <'timeline-trigger-source'> <'timeline-trigger-activation-range'> [ '/' <'timeline-trigger-active-range'> ]? ]#

<timeline-trigger-name> =
none |
<dashed-ident>#

<timeline-trigger-source> =
<single-animation-timeline>#

<timeline-trigger-activation-range> =
[ <'timeline-trigger-activation-range-start'> <'timeline-trigger-activation-range-end'>? ]#

<timeline-trigger-active-range> =
[ <'timeline-trigger-active-range-start'> <'timeline-trigger-active-range-end'>? ]#

<single-animation-timeline> =
auto |
none |
<dashed-ident> |
<scroll()> |
<view()>

<timeline-trigger-activation-range-start> =
[ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#

<timeline-trigger-activation-range-end> =
[ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#

<timeline-trigger-active-range-start> =
[ auto | normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#

<timeline-trigger-active-range-end> =
[ auto | normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#

<scroll()> =
scroll( [ <scroller> || <axis> ]? )

<view()> =
view( [ <axis> || <'view-timeline-inset'> ]? )

<length-percentage> =
<length> |
<percentage>

<scroller> =
root |
nearest |
self

<axis> =
block |
inline |
x |
y

<view-timeline-inset> =
[ [ auto | <length-percentage> ]{1,2} ]#

Examples

Basic usage

In this example, we show how to set up a basic scroll-triggered animation, including defining the trigger using a timeline-trigger shorthand property.

HTML

Our markup contains two <div> elements, one to animate and one to create the trigger on, and 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 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() entry / cover. This specifies the following, all in a single declaration:

  • A timeline-trigger-name value of --t, which is equal to the identifier referenced in the animated <div>'s animation-trigger property value, associating the two together.
  • 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.
  • A timeline-trigger-activation-range of entry, which means that the trigger will activate in the entry range (from the point where the tracked element's block start edge enters the viewport, to the point where its block end edge enters the viewport).
  • A timeline-trigger-active-range of cover, which means that, once activated, the trigger will stay active until the tracked element leaves the cover range (in other words, until it completely leaves the viewport).
css
div.animated {
  animation: rotate 3s infinite linear both;
  animation-trigger: --t play pause;
}

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

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. The rotation will start when the tracked element enters the entry range down the bottom of the viewport, but won't stop again until it has completely exited the viewport.

Multiple timeline-trigger values

In this example, we build on the previous example to demonstrate how multiple timeline-trigger values can be set on the same element, creating multiple triggers that can be used to trigger multiple animations.

HTML

The markup for this example is exactly the same as the previous example markup except that we have included one extra animated <div> element with a class of animated2. This example has a total of two animated elements and one element to create triggers on.

CSS

The CSS is very similar to the previous example, except that in this case we have separate animation and animation-trigger properties applied to the two animated <div> elements. Each one has a different animation that is triggered by a separate timeline trigger, and different <animation-action> values applied. The first animation plays on activation and plays in reverse on deactivation, whereas the second one plays on activation and pauses on deactivation.

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

div.animated2 {
  animation: up-down 1s infinite linear both;
  animation-trigger: --t2 play pause;
}

Next, we give the animated elements fixed positioning like in the previous example, but we give them different left values so that they don't sit on top of one another.

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

div.animated {
  left: 25px;
}

div.animated2 {
  left: 150px;
}

We then set a timeline-trigger value on the .trigger <div> that contains two separate values. Each one has a separate timeline-trigger-name and different timeline-trigger-activation-range and timeline-trigger-active-range values so that the two animated elements start and stop their animations at different offsets.

css
div.trigger {
  timeline-trigger:
    --t view() entry / cover,
    --t2 view() contain;
}

Finally, we define the @keyframes for the two animations.

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

  to {
    rotate: 360deg;
  }
}

@keyframes up-down {
  0% {
    translate: 0 0;
  }

  25% {
    translate: 0 25px;
  }

  50% {
    translate: 0 0;
  }

  75% {
    translate: 0 -25px;
  }

  100% {
    translate: 0 0;
  }
}

Result

The rendered result looks like this:

Try scrolling the content. The first animated element will start to rotate when the tracked element enters the entry range down at the bottom of the viewport, and will start to rotate in reverse when the tracked element has completely exited the viewport. The second animated element will start to move up and down when the tracked element has completely entered the viewport, and stop when it starts to exit again.

Specifications

Specification
CSS Animations Level 2
# timeline-trigger-shorthand

Browser compatibility

See also