Do you want code or template?

1. Save time and import template

Avoid the design headache and use my ScrollTrigger Template

2. Get code and classes here:

Classes:

				
					main

row

card card-left

card card-right
				
			

Use this javascript code:

				
					<style>
    .card{
        will-change: transform;
    }
</style>

<!-- Add these to your Elementor page head or footer -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/ScrollTrigger.min.js"></script>


<script>
document.addEventListener("DOMContentLoaded", function() {
    // Ensure GSAP and ScrollTrigger are available
    if (typeof gsap !== "undefined" && typeof ScrollTrigger !== "undefined") {
        gsap.registerPlugin(ScrollTrigger);

        // Define different movement values for desktop and mobile
        const isMobile = window.innerWidth <= 768;

        const leftXValues = isMobile ? [-1500, -1500, -500] : [-800, -900, -400];
        const rightXValues = isMobile ? [1500, 1500, 500] : [800, 900, 400];
        const leftRotationValues = isMobile ? [-45, -40, -50] : [-30, -20, -35];
        const rightRotationValues = isMobile ? [45, 40, 50] : [30, 20, 35];
        const yValues = isMobile ? [200, -300, -700] : [100, -150, -400];

        gsap.utils.toArray(".row").forEach((row, index) => {
            const cardLeft = row.querySelector(".card-left");
            const cardRight = row.querySelector(".card-right");

            gsap.fromTo(cardLeft, 
                { x: 0, y: 0, rotation: 0 },
                {
                    x: leftXValues[index],
                    rotation: leftRotationValues[index],
                    scrollTrigger: {
                        trigger: ".main",
                        start: "top 80%",
                        end: "150% bottom",
                        scrub: true,
                        onUpdate: (self) => {
                            const progress = self.progress;
                            gsap.set(cardLeft, {
                                x: progress * leftXValues[index],
                                y: progress * yValues[index],
                                rotation: progress * leftRotationValues[index]
                            });
                        },
                    },
                }
            );

            gsap.fromTo(cardRight,
                { x: 0, y: 0, rotation: 0 },
                {
                    x: rightXValues[index],
                    rotation: rightRotationValues[index],
                    scrollTrigger: {
                        trigger: ".main",
                        start: "top 80%",
                        end: "150% bottom",
                        scrub: true,
                        onUpdate: (self) => {
                            const progress = self.progress;
                            gsap.set(cardRight, {
                                x: progress * rightXValues[index],
                                y: progress * yValues[index],
                                rotation: progress * rightRotationValues[index]
                            });
                        },
                    },
                }
            );
        });
    } else {
        console.error("GSAP or ScrollTrigger not found.");
    }
});
</script>

				
			

Background color:
#FBFBFB

Images I used in my video:

Download section separately:

Get lotte animation from video:

Youtube tutorial:

Want more GSAP tutorials?

Want more GSAP blog post?