How to create stacking & image masking on pinning containers with Elementor and GSAP

SHARE

SIGN UP FOR THE NEWSLETTER

Your subscription could not be saved. Please try again.
Your subscription has been successful.


Code:

JavaScript

<!-- GSAP Core -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>

<!-- GSAP ScrollTrigger Plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>

<script>

document.addEventListener("DOMContentLoaded", function () {
  let sections = gsap.utils.toArray(".project-section");
  const gap = 200; 
  const sectionHeight = window.innerHeight * 0.5;

  sections.forEach((section, index) => {
    let mask = section.querySelector(".image-mask");
    let isLast = index === sections.length - 1;
    
    // Define the start trigger.
    let startVal = index === 0 ? "top top" : `top top+=${index * gap}`;
    
    let pinDuration;
    if (index === 0) {
      // Extend the pin duration for the first section with an extra multiplier.
      pinDuration = "+=" + (sectionHeight + (sections.length * gap * 1.2));
    } else if (isLast) {
      pinDuration = "+=20%";
    } else {
      pinDuration = "+=" + (sectionHeight + ((sections.length - index - 1) * gap));
    }
    
    // Create the timeline for pinning the section.
    gsap.timeline({
      scrollTrigger: {
        trigger: section,
        start: startVal,
        end: pinDuration,
        pin: true,
        pinSpacing: false,
        scrub: 1,
        anticipatePin: 1,
        // markers: true, // Uncomment for debugging.
      }
    });
    
    // Animate the image mask over the scroll duration.
    gsap.to(mask, {
      height: "20%",
      duration: 1, 
      ease: "power2.out",
      scrollTrigger: {
        trigger: section,
        start: startVal,
        end: pinDuration,
        scrub: 1,
        // markers: true, // Uncomment for debugging.
      }
    });
  });
});

</script>

CSS

.image-mask {
  width: 100%;
  height: 100%; /* the starting height; this will be animated */
  overflow: hidden;
  transform-origin: center top;
  transition: transform 0.9s ease-out;
}

.project-section{
    height: 70vh;
}



Video:

SIGN UP FOR THE NEWSLETTER

Your subscription could not be saved. Please try again.
Your subscription has been successful.