Jump to content
Search Community

Nextjs / Gsap : Horizontal scroll / how container section need to feet exactly to his child

Suz88 test
Moderator Tag

Recommended Posts

Hello, I'm new to the implementation of gsap's horizontal scrolling in Nextjs :)

 

However, I more or less succeeded in doing what I wanted with the view of the solutions provided by the various posts relating to Nextjs, but i'm dry on the implementation of the size of my container which must imperatively be the size of its children! Indeed the container (green) must imperatively stop where the last of the children ends up (purple) except I can't manage to make sure that the last one adapts dynamically (in fact my client can add / remove specialties because in my app I have a backend that dynamically retrieves children and generates them according to the db)

 

https://stackblitz.com/edit/nextjs-8gdt9v?file=components%2FSpecialties%2Findex.tsx

 

I suspect that this must have an impact on the xPercent property or the end() property of my gsap.to but I can't manage to implement it correctly and to control the size of my container in the right way. Or in other way the last child can be stuck at the end of the container and cannot be scrolled at the beginning idk how to solved it ! 

Can u help me to resolve my pb with any suggestions :) ? Ty and have a good day 

image.png.7cf4867d34127faca1a02824af65228c.png

Link to comment
Share on other sites

Hi @Suz88 and welcome to the GreenSock forums!

 

The issue is that the approach with xPercent: -100 * items.length - 1  works when the item's width is 100% of it's parent element, which is not your case. For this you need the total width of all the elements and the parent element as well, especially since is not 100% of the screen width.

 

This seems to work as you expect:

useIsomorphicLayoutEffect(() => {
  gsap.registerPlugin(ScrollTrigger);

  let sections = gsap.utils.toArray('.item');
  const container: HTMLElement = document.querySelector('.wrapper')!;

  let ctx = gsap.context(() => {
    let totalWidth = 0;
    const listContainer = document.querySelector('.list-container');
    sections.forEach((s) => {
      totalWidth += s.clientWidth;
    });
    totalWidth -= listContainer.clientWidth;
    gsap.to(sections, {
      x: -totalWidth,
      ease: 'none',
      scrollTrigger: {
        pin: true,
        trigger: container,
        scrub: 1,
        end: () => '+=' + `${container.offsetWidth}`,
      },
    });
  }, container);

  return () => ctx.revert();
}, []);

return (
  <div data-scroll-section className={`wrapper ${styles.specialties}`}>
    <div className={styles.title}>{'TITLE'}</div>
    <div className={`list-container ${styles.list}`}>
      {data.map((specialty, i) => {
        return (
          <div className={`item ${styles.specialty}`} key={i}>
            <motion.div
              className={`${styles.informations}${
                active === i ? styles.active : ''
              }`}
              onHoverStart={() => setHover(i)}
              onHoverEnd={() => setHover(-1)}
            >
              <motion.div className={styles.number}>{`0${i}`}</motion.div>

              <Link href={''} className={styles.name}>
                <motion.p>{specialty.title}</motion.p>
              </Link>
            </motion.div>
          </div>
        );
      })}
    </div>
  </div>
);

Finally when you add new elements to the list, is important to call ScrollTrigger.refresh() in order to get the new start and end points.

 

Hopefully this helps. Let us know if you have more questions.

Happy Tweening!

  • Like 4
Link to comment
Share on other sites

Sorry for the inconvenience again but I would like to understand why the calculation of the size of my container (during the first render does not run properly !

 

https://stackblitz.com/edit/nextjs-rvczfa?file=pages%2Fresults.tsx,components%2FResults%2Findex.tsx

 

In my case image div are the problem ! Indeed if you click on one of the links leading to a horizontal scroll the size of the container does not include all the elements (probably due to a too fast rendering even if the latter has all the images). Except if you refresh simply the page size, once loaded,  is good or if we go back to the Home page and again on the same page the size is good why? Why during the first render and only there the size of the container does not take into account the size of all the images? For me useIsomorphicLayoutEffect is done too quickly even before having all the images how to delay its execution to the image fully loaded in my case, or maybe it's an other probleme 

 

Thank you for your help or the tracks that I could approach in order to solve my problem,

 

Good day to you :)

image.png

Link to comment
Share on other sites

Hi,

 

I've been fiddling with your example quite some time and I can't find the reason for this behaviour. I can actually see the problem that you mention, there is no doubt about it, but I tried the window load event as the simplest and perhaps less recommended possible solution and the event is not triggered in the effect hook.

 

I also tried using a setTimeout with over two seconds to call a ScrollTrigger.refresh() method that should correct this, this also didn't work.

 

Even a window resize (which triggers a ScrollTrigger refresh event) doesn't do anything. As you can see I've tested a lot of alternatives.

 

I see that your example has a lot of stuff installed so there is a good chance that this has to do with that. The only thing I didn't had time to do was to isolate the code in a codepen example or a Next app without any other package installed. I'd strongly suggest you to do that and start adding stuff until somethin breaks and you'll find the culprit of this situation.

 

Sorry I couldn't be of more assistance.

Happy Tweening!

Link to comment
Share on other sites

Ty for your answer Rodrigo but unfortunately after having removed almost all the useless packages and cleared my code in order to keep only the essentials I still have this display problem which remains more than problematic in my case for a dynamic rendering display !

 I tried everything telling myself that it was due to flexbox so I tried with grid or other tricky solution the only place where I cheated is to put an apsect-ratio: 16/9 on the result div in order to force the wrapper container size, however, from a rendering point of view and clean display, we are far from the expected result! I'm at an impasse ^^ I'm going to put this aside hoping to find a solution in the coming days or if someone else goes through this maybe he will see a way to find a solution to control size of container enveloping the children at render time without the latter not forgetting half of them along the way !

Have a good day  :D 

Link to comment
Share on other sites

Hi,

 

The weekend paid off so I'm coming to share the solution if anyone is interested :)

 

I took up a thread where Rodrigo had found the problem ^^ (https://greensock.com/forums/topic/34287-scrolltriggerrefresh-not-working-upon-changing-route-in-nextjs/) indeed there he explains that: "You have to wait for the image to load or give the image a specific height in order to avoid the problem. Basically the ScrollTrigger calculations are done before the image loads, so once the image is ready, there is a layout change causing the problem."

 

So here it is either you put a fixed size to your images or you write a function in your useIsomorphicLayoutEffect which comes to wait for the recovery of the images BEFORE launching the scrollTrigger which allows to have a more flexible image size which adapts good at different screen sizes :)

 

However, I have another question (never 2 without 3 as said x))

 

I would like to make sure to use react-transition-group in my application in order to have beautiful transition animation between pages, however this breaks my scrollTrigger and my horizontal scroll so that it would be the right solution for me to use next/gsap together with react-transition-group? What am I missing in my implementation? https://stackblitz.com/edit/nextjs-rvczfa?file=pages%2Findex.tsx,styles%2Fglobals.scss,pages%2Fresults.tsx,components%2FLayout%2Findex.tsx,pages%2F_app.tsx

 

Thank you and good day :) 

  • Like 2
Link to comment
Share on other sites

Hi,

 

There are a few pointers I can give you in this particular case:

5 hours ago, Suz88 said:

I took up a thread where Rodrigo had found the problem indeed there he explains...

Finally don't listen to that guy, he doesn't know what he's talking about ;)

 

Hopefully this helps.

Happy Tweening!

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Hi,

 

Ty Rodrigo for the answers provided and sorry for the delay in answering I had moved on to another feature, but now I come back to this famous page transition with gsap and the implementation of horizontal scroll ^^

I tested the different solutions but without much result whether it was the implementation of pinReparent: true in my instance of scrollTrigger or by stupidly resuming the page transition in the stackblitz with the onEnter() function but nothing there do I always have this problem of horizontal scroll which break when arriving on the page :( 

I reduced my code to the strict necessary in the following stackblitz to reproduce what I have on my main app

https://stackblitz.com/edit/nextjs-pefpra?file=README.md,components%2FSpecialties%2Findex.tsx,components%2FResults%2Findex.tsx,components%2FTransition%2Findex.tsx

 

I do not understand why because logically in view of the solution provided by the thread it should work I must have missed something important but no way to put my finger on it

 

If anyone has an idea to enlighten me that would be a great help.

 

Good day

 

Link to comment
Share on other sites

Hi,

 

I think this is more related to your CSS and the fact that you're not removing the transforms applied by GSAP on the page transition (as mentioned in the thread I linked above) than anything else.

 

I forked our own example and created a horizontal section that's pinned:

https://stackblitz.com/edit/nextjs-56kiof?file=pages%2Fspecialties.js

 

Is worth noticing that this is not working as expected in Stackblitz. We'll check with them and see what could be the issue, my best guess is that it has something to do with Webcontainer (something they use to build a node environment on the browser). So I created a repo and deployed the site in Netlify and seems to work:

https://github.com/rhernandog/next-pagetransitions-horizontal-scrolltrigger

https://enchanting-kheer-2aaf00.netlify.app/

 

As I mentioned be sure to remove the styles applied in the transition by GSAP:

https://github.com/rhernandog/next-pagetransitions-horizontal-scrolltrigger/blob/horizontal-issue/components/Transition.js#L22-L25

 

Hopefully this helps.

Happy Tweening!

  • Like 2
Link to comment
Share on other sites

Hi Rodrigo,

 

Thank you for the time to give to my concerns it's really cool :) 

 

I downloaded your github repo to work on it and find out why my solution didn't work!

 

So I modified the Specialties page so that it sticks with my page (no vertical scroll) by removing the spacer divs and from here I manage to get the same bug as my situation (indeed I don't I only have a horizontal scroll and only that on my pages) suddenly when arriving from the page the horizontal scroll jumps (at refresh everything is back to normal)

 

Secondly I modified the result page so that it contains exactly what my page contains and the same mm observation the horizontal scroll jumps :(  I really don't understand how or why!

 

The css is limited to the bare minimum and I only added the css from my results page so I don't see why it would break the logic of the horizontal scroll...


https://github.com/init3498/Example2
 

I share my Git repo containing the modification in order to understand where my mistake is because I am going in circles

 

Have a nice day and thank you again for your help.

Link to comment
Share on other sites

Hi,

 

The problem is that the useEffect hook is running immediately when the page component is mounted and the calculations by ScrollTrigger were made when the page was still animating in the page transition, so GSAP was obediently using those. The solution is to wait for the completed state of the transition context instance.

 

useIsomorphicLayoutEffect(() => {
  if (!completed) return;

  const ctx = gsap.context(() => {
    const sections = gsap.utils.toArray(".panel");
    const tl = gsap.timeline({
      scrollTrigger: {
        trigger: ".horizontal-wrapper",
        pin: true,
        markers: true,
        start: "top top",
        end: "+=500%",
        scrub: true,
      }
    })
    .to(sections, {
      xPercent: -100 * (sections.length - 1),
      ease: "none"
    });
  }, main);
  return () => ctx.revert();
}, [completed]);

I updated the Github repo so it reflects the update, the live preview is updated and working as well.

 

Repo

https://github.com/rhernandog/next-pagetransitions-horizontal-scrolltrigger

Live Deploy

https://enchanting-kheer-2aaf00.netlify.app/

 

Hopefully this helps.

Happy Tweening!

  • Like 2
Link to comment
Share on other sites

Hi Rodrigo,

 

Thx a lot for your help, u saved me :D 

 

Last step for me: managing parallax effects with gsap ( i saw that ScrollSmoother tool can do the job i will subscribe to an offer to use it! this looks powerful i hope i will handle this  🙌 ) and manage reveal elements in view with scrollTrigger (text animation / border) ^^

 

My goal in the next few weeks/months is to master gsap in a react/next environment and to be able one day (perhaps) to be able to help another user  

 

Have good day,  you're the best  🧙‍♂️

  • Like 2
Link to comment
Share on other sites

4 hours ago, Suz88 said:

My goal in the next few weeks/months is to master gsap in a react/next environment and to be able one day (perhaps) to be able to help another user  

Can't wait to see you around the forums helping users, which not only feels great but is the best way to learn GSAP actually. My journey started over 11 years ago in the same way and one day after a few months I was a moderator here in the forums. Many of us have followed a similar path and inspired others to do the same, I sure hope that you can join those ranks one day:

Happy Tweening!

  • Like 3
Link to comment
Share on other sites

Hi, 

 

It's me again 🥲,

 

I have a concern about the use of react-transition-group and gsap indeed every time I change the page the current page automatically scrolls to the beginning before triggering the exit animation?

 

On Rodrigo's live example we can notice the same problem !

 

I tried to deactivate the scroll when the user changes page but without effect I always have this problem ^^ do you have an idea of what could cause this? I think this is related to the use of react-transition-group and I can't seem to counter it no matter what I try to do it scroll to the top of the page !

 

I take this opportunity to also ask another question, I'm trying to make a basic parallax effect like we can see in this beautiful website on about part :

 

https://www.studiorhe.com/about

 

Then I tried to reply this in a stackblitz:

 

https://stackblitz.com/edit/nextjs-4cjsly?file=components%2FHome%2Findex.tsx

i try to reproduce this effect between two divs with gsap but all I manage to do is move my image by scrolling in its container, which doesn't is not what I'm looking for I would just like the image div (green) to scroll slowly on the left followed automatically by my next div (pink) without causing a space then that the latter also moves and slightly covers the green div but I dry ! Do I necessarily have to use scrollSmoother and data-speed property for this like I can see on other example but I think it’s a bit overkill for my needs ? I don't know if it's very clear what I'm trying to do  

 

Ty for you’re advices/help if u have time, anyway have a good day :) 

 

Link to comment
Share on other sites

Hi,

 

Just add scroll false in the Link component on your navigation:

<nav>
  <ul>
    <li>
      <Link href="/" scroll={false}>Boxes</Link>
    </li>
    <li>
      <Link href="/scroll" scroll={false}>ScrollTrigger</Link>
    </li>
    <li>
      <Link href="/layers" scroll={false}>Layers Section</Link>
    </li>
  </ul>
</nav>

https://nextjs.org/docs/api-reference/next/link

 

Hopefully this helps.

Happy Tweening!

  • Like 2
Link to comment
Share on other sites

Hi Rodrigo,

 

Yes I know this property and it's not my problem because the component scroll at the beginning (top/left depending on the type of scroll applied) BEFORE the navigation, it scrolls first at the top before while doing the exit animation on the current page and after that no worries doing enter animation and I'm at the start of my next component but I think it's a problem more related to Nextjs or react-transition-group than gsap but I haven't found anything promising allowing me to solve the problem I I will continue to persevere and if I find a solution I will come back to post it here if anyone is interested :) 

 

As for my second question relating to a parallax effect (see detail above in my last message) would you have any tips to advise me? Is the use of scrollSmoother in my case an imperative in order to reproduce the effect I'm looking for :)

 

Anyway, thank you for your quick response, have a nice evening/day ^^

Link to comment
Share on other sites

Hi,

 

I'm not seeing the issue of the scroll going to the top as the out transition is happening 🤷‍♂️

 

As for parallax, there are several examples out there that you can find:

https://www.google.com/search?q=parallax+site%3Acodepen.io%2FGreenSock%2F&oq=parallax+site%3Acodepen.io%2FGreenSock%2F&aqs=chrome..69i57.16543j0j1&sourceid=chrome&ie=UTF-8

 

Here are just a couple of them:

See the Pen QWjjYEw by GreenSock (@GreenSock) on CodePen

 

See the Pen OJyPmgX by GreenSock (@GreenSock) on CodePen

 

Happy Tweening!

  • Like 1
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.
×
×
  • Create New...