More Scroll Snippets
Scroll Sticky Stack — Free GSAP ScrollTrigger Stacking Cards
Scroll Sticky Stack · Scroll · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Scroll Sticky Stack — Cards That Recede as the Next Slides Over

The scroll sticky stack is the popular effect where full-height cards pin one after another and each shrinks and darkens as the following card slides up to cover it, building a tidy deck instead of scrolling away — the storytelling layout from modern product pages. This snippet combines CSS position: sticky with GSAP ScrollTrigger (from a CDN).
Sticky does the stacking
Each card is position: sticky with the same top offset, so as you scroll, a card sticks at that position while the next card scrolls up underneath the previous one's bottom and eventually pins over it. CSS sticky alone produces the overlap for free — no JavaScript needed for the pinning. The cards share a top value so they land in the same place and pile up.
GSAP adds the depth
Sticky alone would just stack flat cards; the recession comes from GSAP. For each card, a tween scales it to 0.86 and dims it with filter: brightness(0.6), driven by a ScrollTrigger whose trigger is the next card. So a card only shrinks while the card after it is moving up to cover it — start: 'top bottom' (next card enters) to end: 'top top' (next card fully overlaps). The result is each card visibly sinking back as it's buried, giving the stack real depth.
Triggering off the next element
The key idea is that each card's animation is keyed to the next card's scroll position, not its own. That's what synchronizes the shrink with the cover: the card behind reaches full small-and-dim exactly when the card in front has completely overlapped it. transform-origin: 50% 0 scales each card from its top edge so it shrinks toward where it's pinned, keeping the top aligned as it recedes.
Scrubbed and reversible
scrub: true and ease: 'none' tie the scale and brightness directly to scroll, so scrolling back up brings each buried card forward again — it grows and brightens as the covering card retreats. Nothing plays on a fixed timeline, so the stack is fully reversible and always matches the scroll position.
Cheap and smooth
The animation only changes transform and filter, both GPU-friendly, and the last card is skipped since nothing ever covers it. Because sticky handles layout and GSAP only animates compositor properties, the effect stays smooth with any number of cards.
Customizing it
Add cards (each with its own accent), change how small or dim they get, adjust the sticky top and card heights, or add a slight y offset for a fanned look. Pair it with stacking scroll cards, a scroll pin steps panel, or scroll 3d cards.
Step by step
How to Use
- 1Add the GSAP CDNsInclude gsap and ScrollTrigger from the CDN panel.
- 2Paste HTML, CSS, and JSFour tall cards render in a stack.
- 3Scroll downEach card pins, then shrinks as the next covers it.
- 4Scroll back upBuried cards grow and brighten again.
- 5Add a cardDrop in another .ss-card with an accent.
- 6Tune the recedeChange the scale and brightness targets.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
CSS does the stacking: each card is position: sticky with the same top offset, so a card sticks while the next scrolls up and pins over it. That overlap is free, with no JavaScript. GSAP adds only the depth — scaling and dimming each card as it is covered — so the two work together.
Each card's tween is triggered by the next card, not itself: from start: top bottom (the next card enters) to end: top top (the next card fully overlaps). So a card reaches its smallest, dimmest state exactly when the card in front has completely covered it, which is what makes the recession read correctly.
transform-origin: 50% 0 scales each card from its top, which is where it pins. As the card shrinks it stays aligned to its sticky position instead of drifting toward its center, so it cleanly recedes behind the covering card with the top edges matching.
Yes. scrub: true and ease: none tie the scale and brightness directly to scroll, so scrolling up brings each buried card forward again — it grows and brightens as the covering card retreats. Nothing plays on a fixed timeline, so the whole stack tracks scroll position in both directions.
Render the cards with position: sticky in CSS, then in a mount effect register ScrollTrigger and loop the card refs, creating each tween triggered by the next card. Return a cleanup that reverts the GSAP context. If cards are dynamic, refresh ScrollTrigger after they render. The sticky CSS ports unchanged.