🚀

Update available

We just released a new resource or update, refresh the Vault to access the latest version.

Cancel

Refresh now

Harri

Profile Picture

Harri

Lemke

Stacking Cards Parallax

Documentation

Webflow

Code

Setup: External Scripts

HTML

Copy
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15/dist/ScrollTrigger.min.js"></script>

Step 1: Add HTML

HTML

Copy
<div class="stacking-cards__collection">
  <div class="stacking-cards__list">
    <div data-stacking-cards-item="" class="stacking-cards__item is--green">
      <h1 class="stacking-cards__item-h"><span class="stacking-card__heading-faded">emerald</span><br>new beginnings</h1>
      <img src="https://cdn.prod.website-files.com/68a581f419b751517e3d40c0/68a58a5f107533572d9566ce_Glass%20and%20Marble%20Cube%20Composition.avif" data-stacking-cards-img="" class="stacking-cards__item-img">
      <div class="stacking-cards__item-top">
        <span class="stacking-card__top-span">Gemstones</span>
        <span class="stacking-card__top-span">01 / 05</span>
      </div>
    </div>
    <div data-stacking-cards-item="" class="stacking-cards__item is--purple">
      <h1 class="stacking-cards__item-h"><span class="stacking-card__heading-faded">amethyst</span><br>supports good health</h1>
      <img src="https://cdn.prod.website-files.com/68a581f419b751517e3d40c0/68a58a5ff31697ad7106fc1d_Minimalist%20Stacked%20Cubes%20(1).avif" data-stacking-cards-img="" class="stacking-cards__item-img">
      <div class="stacking-cards__item-top">
        <span class="stacking-card__top-span">Gemstones</span>
        <span class="stacking-card__top-span">02 / 05</span>
      </div>
    </div>
    <div data-stacking-cards-item="" class="stacking-cards__item is--blue">
      <h1 class="stacking-cards__item-h"><span class="stacking-card__heading-faded">sapphire</span><br>wisdom &amp; learning</h1>
      <img src="https://cdn.prod.website-files.com/68a581f419b751517e3d40c0/68a58a5fe3e373d4afe5f860_Stacked%20Cubes%20on%20Marble.avif" data-stacking-cards-img="" alt="" class="stacking-cards__item-img">
      <div class="stacking-cards__item-top">
        <span class="stacking-card__top-span">Gemstones</span>
        <span class="stacking-card__top-span">03 / 05</span>
      </div>
    </div>
    <div data-stacking-cards-item="" class="stacking-cards__item is--brown">
      <h1 class="stacking-cards__item-h"><span class="stacking-card__heading-faded">topaz</span><br>re-motivating</h1>
      <img src="https://cdn.prod.website-files.com/68a581f419b751517e3d40c0/68a58a5f732de55938114f5f_Minimalist%20Stacked%20Cubes.avif" data-stacking-cards-img="" class="stacking-cards__item-img">
      <div class="stacking-cards__item-top">
        <span class="stacking-card__top-span">Gemstones</span>
        <span class="stacking-card__top-span">04 / 05</span>
      </div>
    </div>
    <div data-stacking-cards-item="" class="stacking-cards__item is--red">
      <h1 class="stacking-cards__item-h"><span class="stacking-card__heading-faded">rose quartz</span><br>peace and love</h1>
      <img src="https://cdn.prod.website-files.com/68a581f419b751517e3d40c0/68a58a5ff1fd91f3ae23c706_Geometric%20Blocks%20Arrangement.avif" data-stacking-cards-img="" class="stacking-cards__item-img">
      <div class="stacking-cards__item-top">
        <span class="stacking-card__top-span">Gemstones</span>
        <span class="stacking-card__top-span">05 / 05</span>
      </div>
    </div>
  </div>
</div>

Step 2: Add CSS

CSS

Copy
.stacking-cards__collection {
  width: 100%;
}

.stacking-cards__list {
  flex-flow: column;
  display: flex;
}

.stacking-cards__item {
  color: #fff;
  border-top-left-radius: 1em;
  border-top-right-radius: 1em;
  flex-flow: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  min-height: 100vh;
  margin-top: -1em;
  padding-top: 5em;
  padding-bottom: 5em;
  display: flex;
  position: relative;
}

.stacking-cards__item.is--green {
  background-color: #1a261e;
}

.stacking-cards__item.is--purple {
  background-color: #544a58;
}

.stacking-cards__item.is--blue {
  background-color: #1a232e;
}

.stacking-cards__item.is--brown {
  background-color: #62594c;
}

.stacking-cards__item.is--red {
  background-color: #1f1715;
}

.stacking-cards__item-h {
  text-align: center;
  text-transform: uppercase;
  margin-top: 0;
  margin-bottom: 0;
  font-family: PP Neue Corp Tight, Arial, sans-serif;
  font-size: 10vw;
  font-weight: 700;
  line-height: .8;
}

.stacking-card__heading-faded {
  opacity: .5;
}

.stacking-cards__item-img {
  aspect-ratio: 1;
  border-radius: .75em;
  width: 30vw;
  margin-top: -1vw;
}

.stacking-cards__item-top {
  justify-content: space-between;
  align-items: center;
  display: flex;
  position: absolute;
  top: 2.5em;
  left: 2.5em;
  right: 2.5em;
}

.stacking-card__top-span {
  font-size: 1em;
  font-weight: 500;
}

Step 2: Add Javascript

Step 3: Add Javascript

Javascript

Copy
gsap.registerPlugin(ScrollTrigger);

function initStackingCardsParallax(){
  const cards = document.querySelectorAll("[data-stacking-cards-item]");
  
  if (cards.length < 2) return;

  cards.forEach((card, i) => {
    // Skip over the first section
    if (i === 0) return;
    
    // When current section is in view, target the PREVIOUS one
    const previousCard = cards[i - 1]
    if (!previousCard) return;
    
    // Find any element inside the previous card
    const previousCardImage = previousCard.querySelector("[data-stacking-cards-img]")
    
    let tl = gsap.timeline({
      defaults:{
        ease:"none",
        duration: 1
      },
      scrollTrigger: {
        trigger: card,
        start: "top bottom",
        end: "top top",
        scrub: true,
        invalidateOnRefresh: true
      }
    })
    
    tl.fromTo(previousCard,{ yPercent: 0 },{ yPercent: 50})
      .fromTo(previousCardImage,{ rotate: 0, yPercent:0 },{ rotate: -5, yPercent: -25 }, "<")
  });
}

// Initialize Stacking Cards Parallax
document.addEventListener("DOMContentLoaded", () =>{
  initStackingCardsParallax();
});

Implementation

Make sure you are not using display: flex; on the parent of your .stacking-cards__collection, this will break the resource. For most users this is the <body> or <main> element.

Cards

The only element(s) required to make this setup work, are the cards you want to 'stack'. Give each card the [data-stacking-cards-item] attribute.

Parallax distance

If you want to change how dramatic the parallax effect is, you can change the yPercent value in the timeline:

// We currently move the card down by 50% of its own height
tl.fromTo(previousCard,{ yPercent: 0 },{ yPercent: 50});
Copy

Animate content in the cards

You can of course only have the cards 'stack' with the parallax effect. But, you can also animate any element inside the card. In our example, we tagged the image inside with [data-stacking-cards-img] so that we can add a tween to the timeline, and animate it.

If you want to add more (or different) items, simply give them an attribute of [data-stacking-cards-X]. With X being variable, give this a logical name. So if it's a heading you want to animate, it would become [data-stacking-cards-heading]. Then, make sure to create a variable for it in the function underneath our current image:

// Find any element inside the previous card
const previousCardImage = previousCard.querySelector("[data-stacking-cards-img]");
const previousCardHeading = previousCard.querySelector("[data-stacking-cards-heading]");
Copy

Then, add any tween to the timeline to animate it:

tl.fromTo(previousCard,{ yPercent: 0 },{ yPercent: 50})
  .fromTo(previousCardImage,{ rotate: 0, yPercent:0 },{ rotate: -5, yPercent: -25 }, "<")
  .fromTo(previousCardHeading,{ autoAlpha: 1 },{ autoAlpha: 0 }, "<");
  // Add more tweens as you wish
Copy

Some quick ideas

It was too much to show in a single demo, but some ideas that you can play with:

  • Fade out the previous card while it's having the parallax content
  • Fade out only an inner container, so the card remains, but the content fades out
  • While the parallax on the card is happening, try scaling it down as well.

Live preview

Osmo Robot AI

Copy context for AI

Beta

Webflow

HTML/CSS/JS

Save video

Copy share link

Resource details

  • Published

    August 20, 2025

  • Category

    Scroll Animations

  • Popularity

    3.4K visitors

  • Need help?

    Join Slack

GSAP
Scrolltrigger
Parallax
Card
Scrolling
Stacked
Ilja van EckIlja van Eck

Creator Credits

We always strive to credit creators as accurately as possible. While similar concepts might appear online, we aim to provide proper and respectful attribution.

s