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.
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 usingtimeline-scope
on thebody
. Any child of thebody
– 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 thedata-active-index
attribute on themain
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-range
s 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.
~
🔥 Like what you see? Want to stay in the loop? Here's how:
Why dont you say mouse aint supported?