This demo has several versions:
ScrollTimeline
ViewTimeline
This demo sports a little carousel. As you scroll the carousel, the markers also indicate which element you are viewing.
The carousel consists of two child elements: a .scroller with the content and a .markers element that holds all markers.
.scroller
.markers
<div data-component="carousel"> <ul class="entries" tabindex="0"> <li><a name="carousel_01"><img src="../shared/img/matroshka-01.svg" alt="" title="" width="222" height="184" draggable="false"></a></li> … </ul> <ul class="markers"> <li><a href="#carousel_01"><span class="sr-only">Photo 1</span></a></li> …ul> </div>
The .scroller has its children laid out on a row, and has overflow-x: scroll applied on it. The .markers are position at the bottom of the carousel. Scroll snapping is used to make sure the carousel stops at a certain item instead of halfway.
overflow-x: scroll
The scroller is decorated with a scroll-timeline. The markers representing each item then use that value as their animation-timeline.
scroll-timeline
animation-timeline
[data-component="carousel"] { .entries { scroll-timeline: --carousel x; } .markers a { animation-timeline: --carousel; } }
Because timeline lookups only happen up the ancestor tree, the markers are not able to find the --carousel timeline – the .entries element is not part of their ancestor tree. To allow the markers to use that timeline, timeline-scope is used on the [data-component="carousel"] itself to hoist up the declared --carousel timeline, giving it a wider reach.
--carousel
.entries
timeline-scope
[data-component="carousel"]
[data-component="carousel"] { timeline-scope: --carousel; }
As there are 5 children, each child gets to run for 20% of the entire scroll range. To achieve this, each marker’s animation-range is set to only its specific sub-part. This is done using a --i custom property that indicates the element its child index.
20%
animation-range
--i
.markers a { animation-range: calc((var(--i) - 1) * 20%) calc(var(--i) * 20% + 1px); }
⚠️ Your browser does not support Scroll-driven Animations. Please use Chrome 115 or newer.