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
/* 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-namevalue representing the trigger's identifying name. Defaults tonone. <'timeline-trigger-source'>-
A
timeline-trigger-sourcevalue representing the trigger's timeline. Defaults toauto. <'timeline-trigger-activation-range'>-
A
timeline-trigger-activation-rangevalue representing the trigger's activation range. Defaults tocover. <'timeline-trigger-active-range'>-
A
timeline-trigger-active-rangevalue representing the trigger's activation range. Defaults to the same value as thetimeline-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:
.trigger {
timeline-trigger: --my-trigger view() entry / entry exit 50%;
}
An element with this declaration set will have:
- An identifying
timeline-trigger-nameof--my-trigger. - A
timeline-trigger-sourcevalue ofview(), 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 theentryrange and 50% of the way through theexitrange (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:
.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 value | as each of the properties of the shorthand:
|
|---|---|
| Applies to | all elements |
| Inherited | no |
| Computed value | as each of the properties of the shorthand:
|
| Animation type | as 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.
<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-namevalue of--t, which is equal to the identifier referenced in the animated<div>'sanimation-triggerproperty value, associating the two together. - A
timeline-trigger-sourcevalue ofview(), 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-rangeofentry, which means that the trigger will activate in theentryrange (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-rangeofcover, which means that, once activated, the trigger will stay active until the tracked element leaves thecoverrange (in other words, until it completely leaves the viewport).
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.
div.animated {
position: fixed;
top: 25px;
left: 25px;
}
Finally, we define the @keyframes for the rotate animation:
@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.
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.
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.
div.trigger {
timeline-trigger:
--t view() entry / cover,
--t2 view() contain;
}
Finally, we define the @keyframes for the two animations.
@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> |