Scroll-driven animated card stack with scroll snap events

Recording of Paul’s demo

Dissecting and reworking a very nice demo by Paul Noble.

~

Card Stack Demo

Paul Noble created an AMAZING scroll-driven animations demo in which you can drag cards from a card stack. As he describes it:

Card stack using scroll-driven animation w/ snapping. Just a few lines of JS, zero dependencies.

Try it out (in Chrome) right here:

See the Pen
Scroll-driven animated card stack with scroll snap events.
by Paul Noble (@paulnoble)
on CodePen.

The logic/math used for the stack is based on this thread by Nate Smith

~

💁‍♂️ Unfamiliar with Scroll-Driven Animations? Don’t worry, I’ve created a free video course “Unleash the Power of Scroll-Driven Animations” which teaches you all there is to know about Scroll-Driven Animations.

Poster frame of the fist episode of the series

Go check it out to become an expert in Scroll-Driven Animations!

~

Dissecting the code

On social media I already shared (Twitter, Mastodon) how Paul built it:

Invisible Scroller
The first clever thing Paul is doing there is using an invisible scroller laid on top of the stack of cards. This scroller gets a ScrollTimeline named --scroll-timeline attached to it.
Hoisting the Timeline
To make the .card-stack see the --scroll-timeline, it gets hoisted using timeline-scope on the body. Any child of the body – including .card-stack – can therefore use that --scroll-timeline.
Scroll-Snapping
To make the cards always show at the center, CSS scroll-snapping is used.
Snap Events
In his demo, Paul also uses the new scrollsnapchange event to let the markup know which card has snapped. This is propagated through the data-active-index attribute on the main element.
Custom animations based on which card has snapped
Based on the data-active-index attribute, different animations are attached to the cards: the snapped card gets an active animation – which rotates in 3D around the stack – and the non-snapped cards get an inactive animation – which rotates the card around its base.

~

Remixing the demo

Paul’s demo is amazing but also hard to read because the Sass code uses quite some some math to generate keyframes for each card. As hinted on social media I was quite sure that the effect can also be done using shared keyframes for each card. To attach the keyframes to a single .card a ViewTimeline on the linked .scroll-item can be used, and using animation-range it’s possible to limit when the animation should run.

Yesterday evening I put my money where my mouth is and took my idea for a spin. The result is not 100% perfect – there are some 3D stacking issue, most likely I need to tweak the animation-ranges a bit more – but the result comes pretty close to the original:

See the Pen
Scroll-driven animated card stack with scroll snap events (Vanilla)
by Bramus (@bramus)
on CodePen.

While at it, I also reworked the scrollSnapChange logic to use event.snapTargetInline and by also providing a fallback using IntersectionObserver in browsers with no support for the Snap Events.

~

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

1 Comment

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.