Scroll-driven animation

The properties that link animations to scrolling instead of the clock. A scroll timeline tracks how far a scroll container has scrolled; a view timeline tracks how far an element has moved through its scroll container's visible area. An animation picks a timeline with animation-timeline, which is listed with the other animation properties under Transitions & animation. The anonymous timeline functions scroll() and view() are under Easing & timeline functions. Timeline triggers, which start a normal time-based animation when scrolling reaches a point, are at the end of the page.

Scroll timelines

scroll-timeline

Shorthand that turns a scroll container into a named timeline: a name, then optionally the axis to track. Its progress goes from 0% at the start of the scroll range to 100% at the end.

Syntax[ <'scroll-timeline-name'> <'scroll-timeline-axis'>? ]#
InitialSee individual properties
Applies toAll elements
InheritedNo
PercentagesSee individual properties
AnimationNot animatable
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1
.gallery { overflow-x: auto; scroll-timeline: --gallery inline; }
.gallery-progress { animation: grow linear both; animation-timeline: --gallery; }
Name a horizontal scroller's timeline and drive a descendant's animation from it.

scroll-timeline-name

The name of the scroll timeline an element defines. Names are dashed identifiers such as --page. The element itself and its descendants can then use the name in animation-timeline.

Syntax[ none | <dashed-ident> ]#
Initialnone
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

scroll-timeline-axis

Which scroll direction a scroll timeline tracks: the block or inline axis of the writing mode, or the physical x or y axis.

Syntax[ block | inline | x | y ]#
Initialblock
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

View timelines

view-timeline

Shorthand that makes an element the subject of a named view timeline: a name, then optionally the axis and the insets. The timeline tracks the element as it scrolls into view, across, and out of view in its nearest scroll container.

Syntax[ <'view-timeline-name'> [ <'view-timeline-axis'> || <'view-timeline-inset'> ]? ]#
InitialSee individual properties
Applies toAll elements
InheritedSee individual properties
PercentagesSee individual properties
AnimationSee individual properties
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

A view timeline is divided into named ranges that animation-range can refer to: cover (from first appearing to fully gone), contain (while fully inside, or fully covering, the scrollport), entry and exit (crossing the start and end edges), and entry-crossing and exit-crossing.

view-timeline-name

The name of the view timeline an element defines, as a dashed identifier. The element and its descendants can then use the name in animation-timeline.

Syntax[ none | <dashed-ident> ]#
Initialnone
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

view-timeline-axis

Which scroll direction a view timeline tracks: block, inline, x or y.

Syntax[ block | inline | x | y ]#
Initialblock
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

view-timeline-inset

Moves the start and end edges of the area a view timeline treats as visible, inwards for positive values. Use it when a fixed header or footer covers part of the scrollport. auto uses the scroll container's scroll-padding.

Syntax[ [ auto | <length-percentage> ]{1,2} ]#
Initialauto
Applies toAll elements
InheritedNo
PercentagesRelative to the matching dimension of the scrollport
AnimationBy computed value type
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

Attaching timelines

An animation follows a scroll or view timeline once animation-timeline names one, or uses scroll() or view(). The keyframes then map onto scroll progress instead of time, so the duration is left as auto and the easing is usually linear. Write animation-timeline after the animation shorthand, which resets it.

@keyframes grow { from { scale: 0 1; } to { scale: 1 1; } }

.reading-progress {
  position: fixed;
  inset: 0 0 auto;
  height: 4px;
  background: currentColor;
  transform-origin: left;
  animation: grow linear both;
  animation-timeline: scroll(root block); /* the page's own scroll position */
}
A reading-progress bar: the bar's width follows how far the page has been scrolled.

animation-range

Shorthand for the part of the timeline an animation is attached to: where it starts and where it ends. Outside that range the animation is inactive, or filled according to animation-fill-mode.

Syntax[ <'animation-range-start'> <'animation-range-end'>? ]#
InitialSee individual properties
Applies toSee individual properties
InheritedSee individual properties
PercentagesSee individual properties
AnimationSee individual properties
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

A range name on its own covers that whole range, so animation-range: entry means entry 0% entry 100%.

@keyframes fade-in { from { opacity: 0; translate: 0 2rem; } }
.card {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry;
}
Each card fades and slides in while it enters the scrollport.

animation-range-start, animation-range-end

The point on the timeline where the animation starts, or ends. normal is the start, or end, of the whole timeline; a length or percentage is measured along the whole timeline; a range name such as cover or contain, with an optional percentage, is measured within that range.

Syntax[ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#
Initialnormal
Applies toAll elements
InheritedNo
PercentagesRelative to the named timeline range if one is given, otherwise to the whole timeline
AnimationNot animatable
SupportChrome 115 · Firefox 159 · Safari 26
Specscroll-animations-1

timeline-scope

Widens the reach of a named timeline. Normally a named scroll or view timeline can only be used by the element that defines it and its descendants; declaring the name on a shared ancestor lets any element inside that ancestor use it, such as a sibling of the scroller. all does this for every name in the subtree.

Syntaxnone | all | <dashed-ident>#
Initialnone
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 116 · Firefox 159 · Safari 26
Specscroll-animations-1
.layout { timeline-scope: --article; }
.article { overflow-y: auto; scroll-timeline: --article; }
.sidebar-progress { animation: grow linear both; animation-timeline: --article; }
A sidebar outside the scroller follows the article's scroll timeline.

Timeline triggers

A timeline trigger watches a scroll or view timeline and fires when it enters a range. The animation it controls then runs on its own clock, at its normal duration, instead of following the scroll position. A trigger is defined with timeline-trigger on one element and used with animation-trigger on the animated element. These properties ship in Chrome only.

timeline-trigger

Shorthand that defines a named timeline trigger: its name, its timeline, and the ranges in which it activates and stays active. The range part is an activation range, optionally followed by / and an active range.

Syntaxnone | [ <'timeline-trigger-name'> <'timeline-trigger-source'> [ <'timeline-trigger-range'> ]? ]#
InitialSee individual properties
Applies toSee individual properties
InheritedSee individual properties
PercentagesSee individual properties
AnimationSee individual properties
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

timeline-trigger-name

The names of the timeline triggers an element defines, as dashed identifiers. animation-trigger refers to them by these names.

Syntaxnone | <dashed-ident>#
Initialnone
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

timeline-trigger-source

The timeline each trigger watches: a named scroll or view timeline, or an anonymous scroll() or view() timeline.

Syntax[ none | auto | [ <dashed-ident> | <scroll()> | <view()> ]+ ]#
Initialauto
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

timeline-trigger-activation-range

Shorthand for the part of the timeline that activates the trigger: when the timeline's progress enters this range, the trigger fires.

Syntax[ <'timeline-trigger-activation-range-start'> <'timeline-trigger-activation-range-end'>? ]#
InitialSee individual properties
Applies toSee individual properties
InheritedSee individual properties
PercentagesSee individual properties
AnimationSee individual properties
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

timeline-trigger-activation-range-start, timeline-trigger-activation-range-end

The start, or end, of a trigger's activation range. The values work the same way as animation-range-start and animation-range-end.

Syntax[ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#
Initialnormal
Applies toAll elements
InheritedNo
PercentagesRelative to the named timeline range if one is given, otherwise to the whole timeline
AnimationNot animatable
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

timeline-trigger-active-range

Shorthand for the part of the timeline in which an activated trigger stays active. Making it wider than the activation range stops the trigger switching on and off when scrolling hovers near an edge.

Syntax[ <'timeline-trigger-active-range-start'> <'timeline-trigger-active-range-end'>? ]#
InitialSee individual properties
Applies toSee individual properties
InheritedSee individual properties
PercentagesSee individual properties
AnimationSee individual properties
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

timeline-trigger-active-range-start, timeline-trigger-active-range-end

The start, or end, of a trigger's active range. They take the same values as the activation range longhands, plus auto.

Syntax[ auto | normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#
Initialauto
Applies toAll elements
InheritedNo
PercentagesRelative to the named timeline range if one is given, otherwise to the whole timeline
AnimationNot animatable
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

animation-trigger

Connects an element's animations to named triggers. Each item names a trigger with a dashed identifier, followed by the actions to take on the animation when that trigger changes state.

Syntax[ none | [ <dashed-ident> <animation-action>+ ]+ ]#
Initialnone
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1

Like the other animation longhands, the list pairs up with animation-name by position.

trigger-scope

Sets the scope of trigger names at an element, in the same shape as timeline-scope does for timeline names: a list of names, all, or none.

Syntaxnone | all | <dashed-ident>#
Initialnone
Applies toAll elements
InheritedNo
AnimationNot animatable
SupportChrome 146 · Firefox no · Safari no
Specanimation-triggers-1