Jump to content
Search Community

need help in scrolltrigger

omi test
Moderator Tag

Go to solution Solved by omi,

Recommended Posts

i trying to create card stacking animation on scroll similar to https://swagapp.com/?ref=godly website.
Query:
How i can set start and End values dynamically  according to the browser because I'm checking on normal desktop (1366 * 768) is working but when i checking on the large device  large white space is showing. how i can the card position always middle of the screen

you can check the reference website but i want exactly

https://swagapp.com/?ref=godly




 

See the Pen jOQjyQG by omi-bhatia (@omi-bhatia) on CodePen

Link to comment
Share on other sites

Hi @omi there are multiple ways

 

You can use function based values, here I just get the current window height and do that times 3

// What you have right now
start: "50% 50%", // when the top of the trigger hits the top of the viewport
end: "100% 40%", // end after scrolling 500px beyond the start
  
// Function based values based on screen size
start: "50% 50%",
end: () => `${window.innerHeight * 3} 40%`, 

 

Also check out gsap.matchMedia() with which you can do css type media queries based on screen size https://greensock.com/docs/v3/GSAP/gsap.matchMedia()

 

Also it is better to animate more performant type properties eg instead of top, try animating y or yPercent

 

After digging some deeper in your code, I have a few more points, check out this video

 

GSAP becomes a lot easier if you leave GSAP for what it is and first focus on CSS. Personally I lay out everything with CSS where I want elements to end up, then I just can do a simple .from() tween to get them where I want them to start from.

 

I've moved a lot of your CSS around and removed the top: 400% offsets, these really over complicate things.  I've used a simple CSS Grid on the parent and set all .cards to lay on top of each other, and I then of set them based on their nth-child position. (same as the video above)

 

It all then looks like this

 

See the Pen VwVJpdP?editors=0100 by mvaneijgen (@mvaneijgen) on CodePen

 

When my CSS is 100% correct I focus on the animation 

 

See the Pen OJaepwQ?editors=0100 by mvaneijgen (@mvaneijgen) on CodePen

 

See there is no ScrollTrigger, that is because the best thing to do when working with ScrollTrigger is to remove it! This seems counter intuitive, but ScrollTrigger is just animating something on scroll, so just focus on the animation at first and only when you're happy with the animation add ScrollTrigger back in. This way you can focus on one part at a time and it will save a lot of headache when debugging. 

 

See the Pen zYMVZJx?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

 

Hope it helps and happy tweening! 

 

  • Like 2
Link to comment
Share on other sites

31 minutes ago, mvaneijgen said:

Hi @omi there are multiple ways

 

You can use function based values, here I just get the current window height and do that times 3

// What you have right now
start: "50% 50%", // when the top of the trigger hits the top of the viewport
end: "100% 40%", // end after scrolling 500px beyond the start
  
// Function based values based on screen size
start: "50% 50%",
end: () => `${window.innerHeight * 3} 40%`, 

 

Also check out gsap.matchMedia() with which you can do css type media queries based on screen size https://greensock.com/docs/v3/GSAP/gsap.matchMedia()

 

Also it is better to animate more performant type properties eg instead of top, try animating y or yPercent

 

After digging some deeper in your code, I have a few more points, check out this video

 

GSAP becomes a lot easier if you leave GSAP for what it is and first focus on CSS. Personally I lay out everything with CSS where I want elements to end up, then I just can do a simple .from() tween to get them where I want them to start from.

 

I've moved a lot of your CSS around and removed the top: 400% offsets, these really over complicate things.  I've used a simple CSS Grid on the parent and set all .cards to lay on top of each other, and I then of set them based on their nth-child position. (same as the video above)

 

It all then looks like this

 

 

 

 

When my CSS is 100% correct I focus on the animation 

 

 

 

 

See there is no ScrollTrigger, that is because the best thing to do when working with ScrollTrigger is to remove it! This seems counter intuitive, but ScrollTrigger is just animating something on scroll, so just focus on the animation at first and only when you're happy with the animation add ScrollTrigger back in. This way you can focus on one part at a time and it will save a lot of headache when debugging. 

 

 

 

 

Hope it helps and happy tweening! 

 

Comment: we want to hide all cards except the first card . did you check the reference website ?
 

Link to comment
Share on other sites

Do you mean that the cards should come from off screen? Then just change where the card should come from. My previous demo transformed them in the Y direction 100% of the height of the card, but below example animates them from a Y of the height of the current window. 

 

See the Pen dyQBWOZ?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

Link to comment
Share on other sites

1 hour ago, mvaneijgen said:

I don't know what you mean. To me it looks exactly like the reference website, the offset might be a bit off, but that you can fix with CSS.

Thanks for quick response. sorry for my bad English
Please check this link
https://prnt.sc/Y6S0lja0p0dc
on viewport one card are showing at one time but when user scroll then next card will show how i can achieve this ?
i hope this helps you to understand but i want to implement
i had implemented the same but only issue the placement of cards is not middle of the screen on every resolution

 

i also checked your codepen you have made same changes in css and  animation but still same issue all cards are showing on viewport default without scrolling
https://prnt.sc/UTtMkcisykS5
 

Link to comment
Share on other sites

19 minutes ago, mvaneijgen said:

Codepen might be weird with window.innerHeight if you fork my latest version and open the debug menu you will see it works as expected. 

 

 

 

Screenshot 2023-08-11 at 13.35.57.jpg

Thanks for quick response and helping 
i have download the codepen any open in browser on large device working fine by on normal resolution (1366 * 768) last card fully visible
tl.from(".panel__card--two", { y: () => window.innerHeight});
can you please explain this logic


Screenshot(4).thumb.png.6002bfdfc4c897eba33bd0bfbce8aa70.png

Link to comment
Share on other sites

1 hour ago, omi said:

normal resolution (1366 * 768) last card fully visible

 

Please remove everything to do with GSAP and check if the issue still persist. I think is probably will. There is no amount of JavaScript that will fix a CSS layout, so it is really import to fix the css before adding any GSAP code. 
 

 

1 hour ago, omi said:

tl.from(".panel__card--two", { y: () => window.innerHeight});
can you please explain this logic

Instead of using a fixed pixel value or a percentage based value you can also do something dynamic. Eg here I get the height of the current window.  This way it is always just off screen. No matter if the screen is 600px high or 3000px 

  • Like 1
Link to comment
Share on other sites

32 minutes ago, mvaneijgen said:

 

Please remove everything to do with GSAP and check if the issue still persist. I think is probably will. There is no amount of JavaScript that will fix a CSS layout, so it is really import to fix the css before adding any GSAP code. 
 

 

Instead of using a fixed pixel value or a percentage based value you can also do something dynamic. Eg here I get the height of the current window.  This way it is always just off screen. No matter if the screen is 600px high or 3000px 


.panel__stack {
  --spacer:4rem;
  min-height: 120vh;
  position: relative;
  display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
grid-column-gap: 0px;
grid-row-gap: 0px;
align-items: center;
justify-items: center;
}

min-height is conflicting with the layout if i'm changing the dimension they will work differently on all devices
can you suggest me how to add the spacing below the last card
 

Link to comment
Share on other sites

CSS, CSS, CSS. It is the most important step when designing a layout for animation. The issue its, that if you put bad CSS in you get bad animations at the other end. I can't fix your layout for you, that is something you have to get better at, keep in mind less is more in this case 

 

I've tried some hacks, to calculate the height of the cards with all there offsets, but I don't know how this will hold up in the real world. Hope it helps and happy tweening! 

 

See the Pen xxQoPjQ?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

  • Like 2
Link to comment
Share on other sites

  • Solution
16 hours ago, mvaneijgen said:

CSS, CSS, CSS. It is the most important step when designing a layout for animation. The issue its, that if you put bad CSS in you get bad animations at the other end. I can't fix your layout for you, that is something you have to get better at, keep in mind less is more in this case 

 

I've tried some hacks, to calculate the height of the cards with all there offsets, but I don't know how this will hold up in the real world. Hope it helps and happy tweening! 

 

 

it seems it's working ver very thanks 

 

Link to comment
Share on other sites

@omi I have created this section, the tricky part was making the buttons work along with the animation itself, I used scrolltoplugin to solve this problem but it create another bug on refresh let me know if you made it work and how you did it 

Link to comment
Share on other sites

7 hours ago, Toso said:

@omi I have created this section, the tricky part was making the buttons work along with the animation itself, I used scrolltoplugin to solve this problem but it create another bug on refresh let me know if you made it work and how you did it 

@Toso  can you share your code because tabs highlight on scrolling is pending

  • Like 1
Link to comment
Share on other sites

  const boxes = gsap.utils.toArray(".epitems__singleItem");
      const scrollNav= gsap.utils.toArray(".scroll-btn");
      let index = 0;
      const endTime = 1000 * boxes.length;
 
      gsap.set(".epitems__singleItem", { position: "absolute", transformOrigin: "top" });
      gsap.set(".epitems__singleItem:not(:first-child)", { yPercent: 140 });
 
      function activeDot() {
        gsap.to(scrollNav, { border: "1px solid transparent", ease: "sine", duration: 0.1 });
        gsap.to(scrollNav[index], { border: "1px solid #391952", ease: "sine", duration: 0.5 });
      }
 
      let boxTL = gsap.timeline({
        scrollTrigger: {
          trigger: main.current,
          start: "top top",
          end: `'+=${endTime}px'`,
          scrub: 2,
          pin: true,
        },
      });
 
 
//*************************************  option 1 for animation
 
 boxes.forEach((e, i) => {
        gsap.set(e, { marginTop: () => i * 15 });
        boxTL.to(e, {
          keyframes: [{ yPercent: 0 }, { scale: () => 0.85 + i * 0.03 }],
          onUpdate: () => {
            index = i;
            activeDot();
          }
        });
      });
 
//*************************  thats the first part make sure its working with you so we can move to the next part and stuff dont get complicated , for the animation when you use onUpdate callback it will solve the problem that you have with tab highlighting   also the animation here is one of 2 options i tried but thats the simple one , the other one i used a nested loop inside onComplete & onReverseComplete callbacks  to get the the same result like the ref section from swag 
 
 
 
 
Link to comment
Share on other sites

 
boxes.forEach((e, i) => {
        gsap.set(e, { marginTop: () => i * 15 });
        boxTL.to(e, {
          yPercent: 0 ,
          onUpdate: () => {
            index = i;
            activeDot();
          },
          onComplete: () => {
            e.classList.add("active-box");
            gsap.utils.toArray(".active-box").forEach((x) => {
              let currentScale = gsap.getProperty(x, "scale");
              gsap.to(x, {
                scale: () => currentScale - 0.025,
              });
            });
          },
          onReverseComplete: () => {
            e.classList.remove("active-box");
            gsap.utils.toArray(".active-box").forEach((x) => {
              let currentScale = gsap.getProperty(x, "scale");
              gsap.to(x, {
                scale: () => currentScale + 0.025,
              });
            });
          },
        });
      });
 
//********************  thats the second option if you want to get the same animation and everything but im still trying to make it better 
 
Link to comment
Share on other sites

1 hour ago, Toso said:
  const boxes = gsap.utils.toArray(".epitems__singleItem");
      const scrollNav= gsap.utils.toArray(".scroll-btn");
      let index = 0;
      const endTime = 1000 * boxes.length;
 
      gsap.set(".epitems__singleItem", { position: "absolute", transformOrigin: "top" });
      gsap.set(".epitems__singleItem:not(:first-child)", { yPercent: 140 });
 
      function activeDot() {
        gsap.to(scrollNav, { border: "1px solid transparent", ease: "sine", duration: 0.1 });
        gsap.to(scrollNav[index], { border: "1px solid #391952", ease: "sine", duration: 0.5 });
      }
 
      let boxTL = gsap.timeline({
        scrollTrigger: {
          trigger: main.current,
          start: "top top",
          end: `'+=${endTime}px'`,
          scrub: 2,
          pin: true,
        },
      });
 
 
//*************************************  option 1 for animation
 
 boxes.forEach((e, i) => {
        gsap.set(e, { marginTop: () => i * 15 });
        boxTL.to(e, {
          keyframes: [{ yPercent: 0 }, { scale: () => 0.85 + i * 0.03 }],
          onUpdate: () => {
            index = i;
            activeDot();
          }
        });
      });
 
//*************************  thats the first part make sure its working with you so we can move to the next part and stuff dont get complicated , for the animation when you use onUpdate callback it will solve the problem that you have with tab highlighting   also the animation here is one of 2 options i tried but thats the simple one , the other one i used a nested loop inside onComplete & onReverseComplete callbacks  to get the the same result like the ref section from swag 
 
 
 
 

@Toso
Thanks for sharing the code do you have demo link to check the output?

Link to comment
Share on other sites

3 hours ago, Toso said:
 
boxes.forEach((e, i) => {
        gsap.set(e, { marginTop: () => i * 15 });
        boxTL.to(e, {
          yPercent: 0 ,
          onUpdate: () => {
            index = i;
            activeDot();
          },
          onComplete: () => {
            e.classList.add("active-box");
            gsap.utils.toArray(".active-box").forEach((x) => {
              let currentScale = gsap.getProperty(x, "scale");
              gsap.to(x, {
                scale: () => currentScale - 0.025,
              });
            });
          },
          onReverseComplete: () => {
            e.classList.remove("active-box");
            gsap.utils.toArray(".active-box").forEach((x) => {
              let currentScale = gsap.getProperty(x, "scale");
              gsap.to(x, {
                scale: () => currentScale + 0.025,
              });
            });
          },
        });
      });
 
//********************  thats the second option if you want to get the same animation and everything but im still trying to make it better 
 

Can you provide the demo link with compelete htm, css and  javascript

Link to comment
Share on other sites

On 8/11/2023 at 8:41 PM, mvaneijgen said:

CSS, CSS, CSS. It is the most important step when designing a layout for animation. The issue its, that if you put bad CSS in you get bad animations at the other end. I can't fix your layout for you, that is something you have to get better at, keep in mind less is more in this case 

 

I've tried some hacks, to calculate the height of the cards with all there offsets, but I don't know how this will hold up in the real world. Hope it helps and happy tweening! 

 

 

 


is it possible to hightlight the navabar according to the section?

Link to comment
Share on other sites

On 8/11/2023 at 8:41 PM, mvaneijgen said:

CSS, CSS, CSS. It is the most important step when designing a layout for animation. The issue its, that if you put bad CSS in you get bad animations at the other end. I can't fix your layout for you, that is something you have to get better at, keep in mind less is more in this case 

 

I've tried some hacks, to calculate the height of the cards with all there offsets, but I don't know how this will hold up in the real world. Hope it helps and happy tweening! 

 

 

 

How to manage the card because on some laptops complete content is not visible is it possible to keep the white space always at bottom of the card at moment card is touching at the bottom of window

Link to comment
Share on other sites

It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or Stackblitz that demonstrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

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

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

Thanks for the Gsap community to help me on this task
minimal demo :

See the Pen yLGYvqp by omi-bhatia (@omi-bhatia) on CodePen



I tired to make the same animation effect like "swagapp" website but i am facing some issue like

1. on pinned the card content is cutting and card is touching at bottom of the window . how i can set the white space at below card?
2. how i can set the delay between timelines for now slide moves very fast.

3. how to make a click functionality so that user can direct go to particular slide means card can  move on scroll and on click.

 

Similar animation like swagapp.com website
 

Edited by omi
forget to add the codepen link
Link to comment
Share on other sites

Hi,

 

I don't really understand what you mean with this:

2 hours ago, omi said:

1. on pinned the card content is cutting and card is touching at bottom of the window . how i can set the white space at below card?

 

@mvaneijgen already linked a video where @Cassie talks about this:

2 hours ago, omi said:

2. how i can set the delay between timelines for now slide moves very fast.

 

2 hours ago, omi said:

3. how to make a click functionality so that user can direct go to particular slide means card can  move on scroll and on click.

Check this example:

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

 

Hopefully this helps.

Happy Tweening!

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