Jump to content
Search Community

Recreating "Pinned content based on section" in NextJS

Kuro091 test
Moderator Tag

Recommended Posts

Hello,

 

I'm trying to recreate this effect, but use NextJS (so basically React).

 

This is what I have so far:

https://codesandbox.io/p/sandbox/withered-shadow-zdcqr1?file=README.md

 

Apologies for the sandbox link as I'm not familiar with Codepen.

 

As you see whenever the scroll hits the "start" point the images disappear immediately. I haven't even plugged in the onUpdate hook yet.

 

This is the effect I'm trying to recreate:

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

Link to comment
Share on other sites

So um fixed it with wrapping it in context and use gsap.to() instead of ScrollTrigger directly. (I think using gsap.to() fixed it)

I fixed it in the same codesandbox

 

https://codesandbox.io/p/sandbox/withered-shadow-zdcqr1?file=README.md

 

However now the pinned element isn't exactly responsive.

 

Upon inspecting the element I find out that gsap adds fixed width, height, etc. to the pinned element, which causes the issue.
Please help :(

Link to comment
Share on other sites

Hi,

 

It seems that the issue is merely in your CSS as the Codepen example you posted seems to work as expected in terms of responsiveness as everything else seems to be working as expected GSAP-wise. Unfortunately your CSS is over 250 lines and we don't have the time resources to comb through it in order to find those issues.

 

My recommendation would be to reduce your example to just the working part (images+text) and completely remove GSAP and ScrollTrigger in order to make your markup responsive. Then create the GSAP animation without ScrollTrigger and when everything is working you add ScrollTrigger to the mix.

 

Sorry I can't be of more assistance.

Happy Tweening!

Link to comment
Share on other sites

16 hours ago, Rodrigo said:

Hi,

 

It seems that the issue is merely in your CSS as the Codepen example you posted seems to work as expected in terms of responsiveness as everything else seems to be working as expected GSAP-wise. Unfortunately your CSS is over 250 lines and we don't have the time resources to comb through it in order to find those issues.

 

My recommendation would be to reduce your example to just the working part (images+text) and completely remove GSAP and ScrollTrigger in order to make your markup responsive. Then create the GSAP animation without ScrollTrigger and when everything is working you add ScrollTrigger to the mix.

 

Sorry I can't be of more assistance.

Happy Tweening!

Hey thanks for the reply!

 

Quote

CSS is over 250 lines

 

Oh sorry those were created with the scaffolder. I wasn't using any of it, but rather made use of tailwindcss in my code. I cleaned up that codesandbox just now and would really appreciate if you or anyone can take a look at it again. Everything relevant is written inside pages/index.tsx, and  styles/globals.css is used for some basic css reset, nothing more.

https://codesandbox.io/p/sandbox/withered-shadow-zdcqr1?file=README.md

 

The gist of it is that instead of a block display with two children of 50% width like in the example, I want to utilize the grid display of two columns. Somehow when I did the switch, if you change the screen size the pinned element keep its width and not changing.

 

The pin property just somehow adds fixed width to whatever element I point it to pin and I think that's the thing causing issue.

Link to comment
Share on other sites

Hi,

 

This could be solved using GSAP MatchMedia. I wasn't able to get the breakpoint you're using in your CSS for changing the display, but basically you can tell GSAP MatchMedia to run some specific code above some breakpoint and below GSAP will immediately revert everything for you, removing all the changes made by any GSAP and ScrollTrigger instances that are scoped inside it.

 

https://greensock.com/docs/v3/GSAP/gsap.matchMedia()

 

To clarify things MatchMedia is a more powerful GSAP Context instance, so you won't need to create both a MatchMedia and Context instances, just MatchMedia:

useLayoutEffect(() => {
  const mm = gsap.matchMedia();
  
  mm.add("(your-breakpoint)", () => {}, scope);
  
  return () => mm.revert();
}, []);

Also we recommend using useLayoutEffect for animations in React. In order to avoid warning or issues with SSR refer to this simple method:

https://greensock.com/react-advanced#useIsomorphicLayoutEffect

 

Finally you have two useEffects in your setup, both with an empty dependencies array. Any particular reason for that? You could concentrate everything in just one. Also in one of them you're not using GSAP Context, I wouldn't recommend that since you're creating fromTo instances in it. You can read more about it here:

 

Hopefully this helps.

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

I was trying to make it responsive (i.e. work with any screens) so there were no breakpoints.

 

Basically, I was trying to copy-parse the whole thing from the original codepen over to NextJs. CSS setup was the same as the original one.

 

Quote

two useEffects in your setup, both with an empty dependencies array.

That was intentional. It just kinda made sense in my mind but yeah now I see there's really no reason to so I edited it to just include one useEffect just now.

 

So I was trying more things to make it working and my findings is that:

 

- If I leave the gsap.to() inside the gsap.context() then the scroll animation works, but not responsive

- If I leave the gsap.to() out of it (essentially not using gsap.context()) then it's responsive (as in if I resize the screen then the width of both elements automatically change accordingly), but then the scroll animation stops working.

 

Maybe because my approach was wrong. My end goal is just to convert the original sample to react code :( I'd appreciate any helps

Link to comment
Share on other sites

Hi,

 

The issue here is that if you don't revert what ScrollTrigger does in order to pin some element, below or above a specific breakpoint, you'll have those styles applied to that element. Is not an issue, just the way ScrollTrigger makes pinning work. That's why I suggested GSAP MatchMedia and I still think is the best approach in this case. Play around with MatchMedia and you'll find out how simple it is to make it work in your particular scenario and for the needs you have.

 

https://greensock.com/docs/v3/GSAP/gsap.matchMedia()

 

Have a look at some of the Codepen examples we have:

https://codepen.io/collection/vBebgJ

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

I tried MatchMedia and the animation went poof as well. However I made it work! By changing context.kill() to context.revert().

 

By the end of this I've come to the conclusion I need to know more about the framework first to make it work. While it's working now it doesn't seem to be the correct solution :)

Link to comment
Share on other sites

Thanks a lot for your help! 😁

 

Regarding the minimal demo I did (try to) provide one.

 

https://codesandbox.io/p/sandbox/withered-shadow-zdcqr1?file=README.md

 

image.png.69843ec1d9c8e6a6f8f8880a48af6a5e.png

 

This is the main driver code. RedSection is just a div with height: 100vh.

 

Everything is written in OrangeSection with TailwindCSS.

 

<section id="content-container" className={`bg-red-100 flex [&>*]:w-1/2`}>
      <div
        id="left-content"
        className="bg-pink-200 max-h-screen translate-x-0 relative [&>*]:absolute [&>*]:opacity-0 [&>*]:invisible"
      >
        <img
          id="img1"
          src="https://placekitten.com/1300/1300?image=1"
          alt="kitty"
        />
        <img
          id="img2"
          src="https://placekitten.com/1300/1300?image=2"
          alt="kitty"
        />
        <img
          id="img3"
          src="https://placekitten.com/1300/1300?image=3"
          alt="kitty"
        />
      </div>

      <div
        id="right-content"
        className="flex flex-col bg-orange-900 [&>*]:py-[50rem] items-start text-5xl"
      >
        <p className="contentMarker" data-marker-content="img1">
          Cat 1
        </p>
        <p className="contentMarker" data-marker-content="img2">
          Cat 2
        </p>
        <p className="contentMarker" data-marker-content="img3">
          Cat 3
        </p>
      </div>
    </section>

This is the setup (which I think is really readable). Then I put everything javascript in an useEffect() (pretty much copy-parsed from the original codepen).

I really did try to reproduce it with as less code as possible.

 

Regardless the problem is resolved so I'm not diving into this too much. On to other cool effects :D

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...