Jump to content


ScrollProxy with Locomotive & Nextjs

Go to solution Solved by GreenSock,

Recommended Posts



im tying to use scrollProxy with locomotive like in the docs with Nextjs. Locomotive works fine but scrollTrigger its always at the initial position. It seams that the scrollTop inside the scrollerPoxy its not returning any value. I made a codesandbox to show the case:

Scroll component: 

Live demo: 


I'm looking for a good way to implement a smooth-scroll in nextjs so if any have an alternative to locomotive and works with gsap it would help any way.

Thx, for the support

Link to comment
Share on other sites

Welcome to the forums, @aroca


We don't really support 3rd party libraries here, but we're happy to answer any GSAP-specific questions. I glanced at your demo and I didn't see any ScrollTriggers set up at all. I wasn't quite clear on what you were expecting to happen. 


These docs might help:


Link to comment
Share on other sites

Hi, thx for the answer.


This is what I have to sync scrollTrigger with locomotive:



          locoScroll.on("scroll", ScrollTrigger.update);

          ScrollTrigger.scrollerProxy(scrollWrapper.current, {
            scrollTop(value) {
              return arguments.length
                ? locoScroll.scrollTo(value, 0, 0)
                : locoScroll.scroll.instance.scroll.y;
            getBoundingClientRect() {
              return {
                top: 0,
                left: 0,
                width: window.innerWidth,
                height: window.innerHeight
            pinType: scrollWrapper.current.style.transform
              ? "transform"
              : "fixed"

          ScrollTrigger.addEventListener("refresh", () => locoScroll.update());


The docs shows a similar example but it seems that the scrollTop() is not working. This  "console.log(locoScroll.scroll.instance.scroll.y);" is working on the example but not there, thats what it makes me think that is something that i made in the wrong way with the scrollProxy.

The animation is here:

  const animationTl = gsap.timeline();
      trigger: ".gsap-container",
      animation: animationTl,
      markers: true,
      start: "top center+=300px",
      end: "top center-=300px",
      scrub: true

    animationTl.to(".square", {
      rotateZ: 90,
      x: "100%"


And it works perfect without locomotive.

What I expect its that scrollTrigger takes the scroll position of locomotive instead of the main scroll as its 0 always with the overfllow: hidden of the body.

Thx for the help, I'll keep searching 😊

Link to comment
Share on other sites

  • Solution

It looks like you forgot to define a "scroller" in your ScrollTrigger - remember, when you create a scrollerProxy(), you're basically saying "whenever someone uses this particular scroller _____, I want to use this special logic for it..."


In your case, you set up the scrollerProxy for scrollWrapper.current but you never defined scroller: scrollWrapper.current on your ScrollTrigger to point it to that one. 

  • Thanks 2
Link to comment
Share on other sites

  • 1 year later...

Hey @aroca, have you ever found a solution for this? 

Link to comment
Share on other sites

What's the problem, @inzn? Got a minimal demo


FYI, I believe LocomotiveScroll changed their API in v4 which affects your scrollerProxy() code:

// old
locoScroll.scrollTo(value, 0, 0)

// new
locoScroll.scrollTo(value, {duration: 0, disableLerp: true})

I'm not sure if that has anything to do with the problem you were facing. I just figured I'd mention it. 

Link to comment
Share on other sites

Hey @GreenSock, thanks for your response! I'm a little confused by your demo because for me nothing is happening. 984120663_Screenshot2023-01-14at9_37_15PM.thumb.png.be72b455c902268d503fa44ad645ff38.png


Maybe I should have clarified a bit better. When we get to the quotes, I want them to move horizontally until the end of the container before further moving down on the page (see below). In my demo, the do move right to left but disappear at start and reappear after end. In your demo, the start marker appears to be fixed as well and therefore does not have any effect on my animation.



Link to comment
Share on other sites

Oh, now I see what's happening. And yeah, it's a 3rd party issue :) 


It was working fine for me...and then I refreshed a few times and noticed it was intermittent. With some digging, I found that the LocomotiveScroll stuff wasn't ready initially (sometimes), so your useEffect() that created your scrollerProxy() was running AFTER your useLayoutEffect() that was creating your tween/ScrollTrigger! Thus your "scroller" on your ScrollTrigger was pointing to null (because LocomotiveScroll wasn't defined yet, so there was no scroll.el). Hence it was not responding to any scroll events on null. 


You should of course makes sure you set up the LocomotiveScroll stuff FIRST, then create your ScrollTrigger pointing to the appropriate "scroller". 





  • Like 1
Link to comment
Share on other sites

@GreenSock Exactly what I was looking for! Thank you so much – immensely  appreciated!! ❤️

Link to comment
Share on other sites

Happy to help. 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.