xoxoxoxo Posted September 21, 2021 Share Posted September 21, 2021 I have awkward behavior in nextjs on route changes. When the route changes successfully, I explicitly call `window.scrollTo(0,0)` to reset the scroll position of the browser. However, on a new page route I'm creating a scroll trigger and also refreshing it which yields into a negative side effect of retaining the previous route's scroll position. does ScrollTrigger.refresh(true) retain the scroll position internally? Thanks. Link to comment Share on other sites More sharing options...
OSUblake Posted September 21, 2021 Share Posted September 21, 2021 Hi @xoxoxoxo Frameworks routers are difficult because they try to control the scroll position. Do you think you can put that in minimal demo? Here's our next.js starter template. https://codesandbox.io/s/gsap-nextjs-starter-jekrn?file=/pages/index.js 1 Link to comment Share on other sites More sharing options...
xoxoxoxo Posted September 23, 2021 Author Share Posted September 23, 2021 I've disabled all scroll controls Nextjs ships with so i'm pretty convinced that it's not the framework. I tried fiddling with ScrollTrigger's source code and adding an early return here, which does not retain the scroll position on route changes. This fixes the issue I'm having on route changes however I can't understand where and why it's being called during runtime. Why is it calling scrollTo? The value arg seems to be the y position of the previous route in my case. Is there a source with comments to understand this better? sc: function sc(value) { if (arguments.length) return; return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0; } Link to comment Share on other sites More sharing options...
GreenSock Posted September 23, 2021 Share Posted September 23, 2021 Are you sure you called kill() on all the ScrollTriggers before you do your route change? Like ScrollTrigger.getAll().forEach(t => t.kill()) ScrollTrigger needs to record the page's scroll position when it does its refresh because it must roll back all of its changes to ensure that all the styling is back to "normal" when doing the start/end calculations. Remember, if you have any pinned elements, they typically add padding and stretch out the page. For example, your native page might be 1000px tall but if you pin an element for 5000px, now your page is 6000px tall, so if you scroll down 3000px and then refresh the browser, it has to restore that after it does all of its teardown & calculations. Otherwise, a 1000px page can't possibly scroll to 3000px natively. See what I mean? But ScrollTrigger has code in place to flush that recorded value if you kill() all your ScrollTriggers. My guess is you forgot to do that(?) Link to comment Share on other sites More sharing options...
xoxoxoxo Posted September 23, 2021 Author Share Posted September 23, 2021 I do kill ScrollTrigger on an individual level rather than all on route change. The return function gets called when component unmounts. React.useEffect(() => { if (ref.current == null) return; const st = ScrollTrigger.create({ trigger: ref.current, pin: true, start: 'top top', pinSpacing: false, }); ScrollTrigger.refresh(true); return () => st.kill(); }, [pageStyle]); Link to comment Share on other sites More sharing options...
xoxoxoxo Posted September 23, 2021 Author Share Posted September 23, 2021 Perhaps the rollback should respect browser's history scrollRestoration property before calling scrollTo? Link to comment Share on other sites More sharing options...
Carsten Hess Posted September 23, 2021 Share Posted September 23, 2021 I had the exact same situation (with Vue.js). I kill'ed the ScrollTrigger when my component was about to die (onBeforeUnmount). But it turned out that it's too late. Using the above advice (ScrollTrigger.getAll().forEach(t => t.kill())) before route changes solved it for me. Link to comment Share on other sites More sharing options...
OSUblake Posted September 23, 2021 Share Posted September 23, 2021 Don't know if this will help because you didn't provide a minimal demo, but you should create and kill your ScrollTriggers with useLayoutEffect. That will also fire a tad earlier than useEffect. Link to comment Share on other sites More sharing options...
xoxoxoxo Posted September 23, 2021 Author Share Posted September 23, 2021 If the unmount happens after route has completed then it doesn't really matter if you're using useLayoutEffect or not. See the log below. Unmount triggers after the route has completed which means the initial page has already rendered. I still think the rollback on refresh should respect browser's scrollRestoration property before calling scrollTo method. Link to comment Share on other sites More sharing options...
OSUblake Posted September 23, 2021 Share Posted September 23, 2021 Can you please make a minimal demo with those logs. It looks like there is a solution. Link to comment Share on other sites More sharing options...
GreenSock Posted September 23, 2021 Share Posted September 23, 2021 13 hours ago, xoxoxoxo said: Perhaps the rollback should respect browser's history scrollRestoration property before calling scrollTo? I don't really see how that'd help. The point here is that when ScrollTrigger does a .refresh() it must record the current scroll position and then when it's done with all its work, restore that. We do plan to add a new ScrollTrigger.clearScrollMemory() method in the next release which will let you manually do it. Link to comment Share on other sites More sharing options...
xoxoxoxo Posted September 29, 2021 Author Share Posted September 29, 2021 I'm using the new api on unmount right after I kill the scroll trigger ScrollTrigger.clearScrollMemory() and it seems to work. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now