Help Needed: GSAP Animation Not Working on Shopify

Hi Shopify Community,

I’m facing an issue with a GSAP animated section on my Shopify site. I’ve created a Pen on CodePen that works perfectly:

CodePen Example

However, when I try to implement the same animation on my Shopify site, it doesn’t work as expected. Here’s what I’ve done so far:

  • Added the HTML to a custom Liquid template block in the theme customizer.
  • Linked my scripts and CSS correctly.
  • I have 3 other GSAP animations on my site, and they all work fine.

I’m wondering if there’s something specific about Shopify that could be blocking this particular animation from functioning. Has anyone else encountered a similar issue, or is there something I’m overlooking?

Any insights or suggestions would be greatly appreciated!

Thanks in advance for your help.

Thank you.

  1. I copied and pasted the HTML directly from CodePen into the custom Liquid template block as HTML. And I’ve checked it.
  2. I did notice my css below. I had to comment out /visibility: hidden;/ or nothing would show. I copied and pasted my CSS directly into an asset file of the same name. I will check for other conflicts.
section.first,

section.second,

section.third {

height: 100%;

width: 100%;

top: 0;

position: fixed;

visibility: hidden;
}
  1. I tried wrapping my script in this already but it did not help.
document.addEventListener("DOMContentLoaded", function () { .... 
});
  1. I’ll give that a try.
  2. Yes I believe I am. I have the paid GSAP account. I’ve checked in console and the GSAP is loading.

The strange thing is, the first 2 (out of 3) sections work, but when scrolling to the third it pauses, pulls up the last section without the scrolling effect and the whole thing disappears.

Here is my custom block code:


CSS

url("https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap");

h2.section-heading {
font-size: clamp(1rem, 5vw, 5rem);
font-family: "Bebas Neue", sans-serif;
font-weight: 400;
text-align: center;
letter-spacing: 0.5em;
margin-right: -0.5em;
color: #cccccc;
width: 90vw;
max-width: 1200px;
text-transform: uppercase;
}

nav.three {
position: fixed;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 5%;
width: 100%;
z-index: 3;
height: 7em;
font-family: "Bebas Neue", sans-serif;
font-size: clamp(0.66rem, 2vw, 1rem);
letter-spacing: 0.5em;
text-transform: uppercase;
}

section.first,
section.second,
section.third {
height: 100%;
width: 100%;
top: 0;
position: fixed;
visibility: hidden;
}

section.first .outer,
section.second .outer,
section.third .outer,
section.first .inner,
section.second .inner,
section.third .inner {
width: 100%;
height: 100%;
overflow-y: hidden;
}

section.first .bg,
section.second .bg,
section.third .bg {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
height: 100%;
width: 100%;
top: 0;
background-size: cover;
background-position: center;
}

section.first .bg h2.section-heading,
section.second .bg h2.section-heading,
section.third .bg h2.section-heading {
z-index: 2;
}

section.first .bg .clip-text,
section.second .bg .clip-text,
section.third .bg .clip-text {
overflow: hidden;
}

.first .bg {
background-image: linear-gradient(180deg,
rgba(0, 0, 0, 0.6) 0%,
rgba(0, 0, 0, 0.3) 100%),
url("https://images.unsplash.com/photo-1617478755490-e21232a5eeaf?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxNzU1NjM5NA&ixlib=rb-1.2.1&q=75&w=1920");
}

.second .bg {
background-image: linear-gradient(180deg,
rgba(0, 0, 0, 0.6) 0%,
rgba(0, 0, 0, 0.3) 100%),
url("https://images.unsplash.com/photo-1617128734662-66da6c1d3505?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxNzc3NTM3MA&ixlib=rb-1.2.1&q=75&w=1920");
}

.third .bg {
background-image: linear-gradient(180deg,
rgba(0, 0, 0, 0.6) 0%,
rgba(0, 0, 0, 0.3) 100%),
url("https://images.unsplash.com/photo-1617438817509-70e91ad264a5?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxNzU2MDk4Mg&ixlib=rb-1.2.1&q=75&w=1920");
}

h2.section-heading * {
will-change: transform;
}

JS/GSAP

document.addEventListener("DOMContentLoaded", function () {

    // Register GSAP plugins
    gsap.registerPlugin(ScrollTrigger, SplitText, Observer);

    let sections = document.querySelectorAll("section"),
        images = document.querySelectorAll(".bg"),
        headings = gsap.utils.toArray(".section-heading"),
        outerWrappers = gsap.utils.toArray(".outer"),
        innerWrappers = gsap.utils.toArray(".inner"),
        splitHeadings = headings.map(
            (heading) =>
                new SplitText(heading, {
                    type: "chars,words,lines",
                    linesClass: "clip-text"
                })
        ),
        navLinks = document.querySelectorAll("nav.three a"), // Select nav.three links
        currentIndex = 0, // Start from the first section
        animating;

    // Set initial states for sections and wrappers
    gsap.set(outerWrappers, { yPercent: 100 });
    gsap.set(innerWrappers, { yPercent: -100 });
    gsap.set(sections[0], { autoAlpha: 1 }); // Prevent the first section from disappearing on load

    function gotoSection(index, direction) {
        // Prevent scrolling past the first and last sections
        if (index < 0 || index >= sections.length) {
            animating = false;
            return;
        }

        animating = true;
        let fromTop = direction === -1,
            dFactor = fromTop ? -1 : 1,
            tl = gsap.timeline({
                defaults: { duration: 1.25, ease: "power1.inOut" },
                onComplete: () => (animating = false)
            });

        if (currentIndex >= 0 && currentIndex !== index) {
            gsap.set(sections[currentIndex], { zIndex: 0 });
            tl.to(images[currentIndex], { yPercent: -15 * dFactor }).set(
                sections[currentIndex],
                { autoAlpha: 0 }
            );
        }

        gsap.set(sections[index], { autoAlpha: 1, zIndex: 1 });
        tl.fromTo(
            [outerWrappers[index], innerWrappers[index]],
            {
                yPercent: (i) => (i ? -100 * dFactor : 100 * dFactor)
            },
            {
                yPercent: 0
            },
            0
        )
            .fromTo(images[index], { yPercent: 15 * dFactor }, { yPercent: 0 }, 0)
            .fromTo(
                splitHeadings[index].chars,
                {
                    autoAlpha: 0,
                    yPercent: 150 * dFactor
                },
                {
                    autoAlpha: 1,
                    yPercent: 0,
                    duration: 1,
                    ease: "power2",
                    stagger: {
                        each: 0.02,
                        from: "random"
                    }
                },
                0.2
            );

        currentIndex = index;
    }

    function handleNavClick(event) {
        event.preventDefault(); // Prevent default anchor link behavior
        const targetId = this.getAttribute("href").substring(1); // Get target section ID
        const targetIndex = Array.from(sections).findIndex(
            (section) => section.id === targetId
        ); // Find the index of the target section
        if (targetIndex !== -1 && targetIndex !== currentIndex) {
            gotoSection(targetIndex, targetIndex > currentIndex ? 1 : -1); // Animate to the target section
        }
    }

    // Add event listeners to navigation links
    navLinks.forEach((link) => link.addEventListener("click", handleNavClick));

    Observer.create({
        type: "wheel,touch,pointer",
        wheelSpeed: -1,
        onDown: () => !animating && gotoSection(currentIndex - 1, -1),
        onUp: () => !animating && gotoSection(currentIndex + 1, 1),
        tolerance: 10,
        preventDefault: true
    });

    // Initialize by showing the first section
    gotoSection(0, 1);

    // Debugging logs
    console.log(gsap); // Should log the GSAP object
    console.log(ScrollTrigger); // Should log the ScrollTrigger object
    console.log(SplitText); // Should log the SplitText object
    console.log(Observer); // Should log the Observer object
    console.log(typeof gotoSection); // Should log 'function' if it's correctly defined
});

You can see the Codepen here: https://codepen.io/517design-the-solid/pen/gONzQNK

And the same code is on a barebones, non-shopify test site here, where it works as expected.
https://gregr79.sg-host.com/

Thanks in advance. Greg

I’ve also put up a new dev site on shopify with only the dawn theme to test if some of my other code was the problem. It’s not. I don’t think Shopify is doing anything wrong but I suspect there is something in shopify’s build that I’m not aware of that is conflicting with my code.

Here is the error I get in console log:

TypeError: Cannot read properties of undefined (reading ‘_gsap’)
at ea (gsap.min.js:10:1076)
at new Tween (gsap.min.js:10:35640)
at Va (gsap.min.js:10:5253)
at Timeline.fromTo (gsap.min.js:10:23501)
at gotoSection (kg-three-face-graph-a.js:48:12)
at onUp (kg-three-face-graph-a.js:99:35)
at sc (Observer.min.js:10:4840)
ea @ gsap.min.js:10
Tween @ gsap.min.js:10
Va @ gsap.min.js:10
fromTo @ gsap.min.js:10
gotoSection @ kg-three-face-graph-a.js:48
onUp @ kg-three-face-graph-a.js:99
sc @ Observer.min.js:10
requestAnimationFrame
tc @ Observer.min.js:10
Bc @ Observer.min.js:10Understand this error