view-timeline
This demo has several versions:
scroll-timeline
ScrollTimeline
This demos sports section that scrolls horizontally as you scroll down.
Original demo by Cameron Knight: https://codepen.io/cameronknight/pen/qBNvrRQ
<section id="sectionPin"> <div class="pin-wrap-sticky"> <div class="pin-wrap">…</div> </div> </div>
@keyframes move { to { /* Move horizontally so that right edge is aligned against the viewport */ transform: translateX(calc(-100% + 100vw)); } } #sectionPin { /* Stretch it out, so that we create room for the horizontal scroll animation */ height: 500vh; overflow: visible; /* To make position sticky work … */ view-timeline-name: --section-pin-tl; view-timeline-axis: block; } .pin-wrap-sticky { /* Stick to Top */ height: 100vh; width: 100vw; position: sticky; top: 0; width: 100vw; overflow-x: hidden; } .pin-wrap { height: 100vh; width: 250vmax; /* Hook animation */ will-change: transform; animation: linear move forwards; /* Link animation to view-timeline */ animation-timeline: --section-pin-tl; animation-range: contain 0% contain 100%; }
By stretching out #sectionPin to a height of 500vh, more scroll estate is created. A ViewTimeline is attached to that element, tracking it as it crosses the scrollport.
#sectionPin
500vh
The intermediary element .pin-wrap-sticky is made sticky, and it’s the .pin-wrap that gets animated on the ViewTimeline.
.pin-wrap-sticky
.pin-wrap
The start position of the horizontal strip .pin-wrap is at 0,0 within its parent. Its end position is a horizontal translation of -100% to which the viewport width is added. If the viewport width were not taken into account, the element would be entirely out of view.
0,0
-100%
⚠️ Your browser does not support Scroll-driven Animations. Please use Chrome 115 or newer.
With CSS view-timeline