alx Posted March 15, 2025 Posted March 15, 2025 Greetings! I have these two simple scrub animations. The first makes each section fade in when it enters and the second makes each section fade out when it leaves. They work fine like this but I imagine there's a way to cleanly combine the two, but I can't figure out how... const fadeIns = gsap.utils.toArray('.d-section'); fadeIns.forEach(fadeIn => { gsap.to(fadeIn, { scrollTrigger: { trigger: fadeIn, start: 'top 66%', end: 'top 33%', scrub: true, }, autoAlpha: 1, ease: 'none', }) }); const fadeOuts = gsap.utils.toArray('.d-section'); fadeOuts.forEach(fadeOut => { gsap.to(fadeOut, { scrollTrigger: { trigger: fadeOut, start: 'bottom 66%', end: 'bottom 33%', scrub: true, immediateRender: false, }, autoAlpha: 0, ease: 'none', }) });
GSAP Helper Posted March 15, 2025 Posted March 15, 2025 Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates 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 dependencies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer. See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen. that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo: 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: React (please read this article!) Next Svelte Sveltekit Vue Nuxt 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. ✅
Solution mvaneijgen Posted March 15, 2025 Solution Posted March 15, 2025 Please include a minimal demo with your question, this saves us a lot of time to help you. Thanks! I would create one timeline with your ScrollTrigger logic on that timeline. Then like you do fade the element in and then a second tween that fades it out again. You probably want to have a moment where the element stays fully visible for a moment, so you can add a small pause to your timeline to have that happen. Duration in scrubbed timelines work a bit differently, maybe this explanation helps you understand. Let's say we have four tweens that all take 1 second to animate and the total ScrollTrigger distance is 400px each tween will then take up 100px. If we remove one tween and make the last tween take 2 seconds the first two tweens will take still 100px, but the last tween will get stretched over the remaining 200px. I've also placed some comments in your JS to explain certain properties, be sure to read through them. Hope it helps and happy tweening! See the Pen emYyvxo?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen.
alx Posted March 15, 2025 Author Posted March 15, 2025 Ok there's a lot of good stuff to study there but I need to update this topic with a pen. What worked in WP doesn't seem to work on this codepen example: See the Pen raNpJdO by alxhrrs (@alxhrrs) on CodePen.
mvaneijgen Posted March 15, 2025 Posted March 15, 2025 The pen you've shared uses none of my suggestions, so I'm a bit lost to what the issues is, beside going back to your old solution?
alx Posted March 15, 2025 Author Posted March 15, 2025 Exactly sorry about that, I realize I didn't really explain my reply. Because in the replies above it was requested that I include a minimal demo, I went ahead and created one and shared it in case it could help with my question. Here's the thing, on my WP site, this same exact code performs perfectly, so I just wanted to 'combine' the scrub animations to make it more efficient, but when I simply recreated the same thing on codepen...suddenly the animations didn't work correctly anymore and I wondered if my gsap code is actually incorrect to begin with and WP is simply forgiving...I hope that makes sense. Let's say, your timeline solution is great but leaves me questioning why animating the trigger element is incorrect. In this case, I understand how you avoid using the element to trigger by simply adding a 'trigger' in the html, but is that how I'm supposed to animate entire sections? Do I really have to add a 'triggering' element to every section?
mvaneijgen Posted March 15, 2025 Posted March 15, 2025 I would have no idea why some code works somewhere else and not on Codepen. Wordpress does not do something inherently different than other web platforms. How ever if you use a off the shelve theme these most of the time load a lot off other stuff, which could interfere with GSAP animations, see https://gsap.com/resources/mistakes/#using-css-transitions-and-gsap-on-the-same-properties for example I also work in Wordpress and if I put something on my site or on Codepen everything works the same, but I build custom themes and are in full control what code gets loaded and when. Not animating the trigger element is just a general tip. Animating the trigger element is totally fine, until it isn't, but if you know what you're doing and what the limitations are (eg you cant move the element you're triggering, this will throw off the ScrollTrigger calculations) you can do it. I've personally spent to much time debugging ScrollTrigger animations only to find out that the issue was that I was animating the trigger element, which made me just have the rule never animate it! But because in your case you're not moving the element it is fine, but when your client requests that the should move up a little while fading in and you then spend the next day debugging why all your ScrollTriggers are off, you'll remember this conversation and it might click why we've warned you for this 😅 I don't like your setup because it targets the same elements with the same properties, but that again comes from years of experience that I never target the same element in different tween with the same property (again have spend to much time debugging those) also because an element can never fade out before it has faded in that to me sounds like a sequence and sequences should be put on a timeline, so that the reason for my suggestions Again if you know what you're doing you can break those rules. Hope it helps and happy tweening!
alx Posted March 15, 2025 Author Posted March 15, 2025 Ah ok, that makes perfect sense! I also use a custom theme but I'll bet there's some css or something that I overlooked that changes the behavior on WP. I'm going to study how to implement your timeline code in my situation because it indeed looks better, I don't like my setup either😅 and I'll remember your warning😆. Thanks again for help and all the best!
alx Posted March 15, 2025 Author Posted March 15, 2025 sorry mvaneijgen i have one last question. i implemented it all and it works like a charm and obviously better than before. i understand everything that's going on in the code except for tl.add(() => {}, "+=1"); in our case, we have start at 66% and end at 33%, but what/how much are you adding with +=1? is it percentage? what does the "1" refer to? i totally get what you said before about durations with scrub being different but i don't understand this one line.....
mvaneijgen Posted March 16, 2025 Posted March 16, 2025 Yes that is this: Quote Duration in scrubbed timelines work a bit differently, maybe this explanation helps you understand. Let's say we have four tweens that all take 1 second to animate and the total ScrollTrigger distance is 400px each tween will then take up 100px. If we remove one tween and make the last tween take 2 seconds the first two tweens will take still 100px, but the last tween will get stretched over the remaining 200px. The "+=1" uses the position parameter to add 1 second to the and of the previous tween. If you do not define a duration in a tween the duration gets set to 0.5 seconds, so you now have two tweens of 0.5 seconds = 1 second and a tween (that does nothing) of 1 second, so your total timeline duration is 2 seconds. Now if we were to map that to your ScrollTrigger, let say your ScrollTrigger has a distance of 400px, the first tween fades in over 100px your fade out tween uses the same distance eg 100px and the remaining 1 second gets stretched over the 200px If you don't do this it will start fading out again directly after it fades in, which is probably not what you want.
alx Posted March 16, 2025 Author Posted March 16, 2025 Quote If you don't do this it will start fading out again directly after it fades in, which is probably not what you want. Exactly, I noticed this when I tried it commenting out the "+=1". Quote Now if we were to map that to your ScrollTrigger, let say your ScrollTrigger has a distance of 400px, the first tween fades in over 100px your fade out tween uses the same distance eg 100px and the remaining 1 second gets stretched over the 200px I get it, I was getting lost in the relativity of my units. Let's say I used '75%' and '25%', this would mean that it starts at 75% -> pauses for 50% -> and then ends at 25%: because 25% + 50% + 25% = 100% Thanks again for all the help man!
alx Posted March 16, 2025 Author Posted March 16, 2025 In case anyone stumbles upon this in the future, this is the corrected pen: See the Pen YPzYMqK by alxhrrs (@alxhrrs) on CodePen.
Rodrigo Posted March 17, 2025 Posted March 17, 2025 Hi, Actually that add() instance in the middle of the Timeline is not needed because the position parameter allows you to place the next to() instance of the timeline anywhere you want (time-wise of course), so this: tl.to(q('.d-section-wrapper'), { autoAlpha: 1, }); tl.add(() => {}, "+=1"); tl.to(q('.d-section-wrapper'), { autoAlpha: 0 }); Is the same as this: tl.to(q('.d-section-wrapper'), { autoAlpha: 1, }); tl.to(q('.d-section-wrapper'), { autoAlpha: 0 }, "+=1"); Hopefully this clear things up Happy Tweening!
alx Posted March 17, 2025 Author Posted March 17, 2025 Oh cool! I'd always use that for delays and such but you're right, I have to get used to using timelines this way, looking at a timeline with another perspective. Thanks! 1
iceland Posted May 13, 2025 Posted May 13, 2025 On 3/15/2025 at 9:54 AM, alx said: Greetings! I have these two simple scrub animations. The first makes each section fade in when it enters and the second makes each section fade out when it leaves. They work fine like this but I imagine there's a way to cleanly combine the two, but I can't figure out how... const fadeIns = gsap.utils.toArray('.d-section'); fadeIns.forEach(fadeIn => { gsap.to(fadeIn, { scrollTrigger: { trigger: fadeIn, start: 'top 66%', end: 'top 33%', scrub: true, }, autoAlpha: 1, ease: 'none', }) }); const fadeOuts = gsap.utils.toArray('.d-section'); fadeOuts.forEach(fadeOut => { gsap.to(fadeOut, { scrollTrigger: { trigger: fadeOut, start: 'bottom 66%', end: 'bottom 33%', scrub: true, immediateRender: false, }, autoAlpha: 0, ease: 'none', }) });
ryan_labar Posted May 13, 2025 Posted May 13, 2025 You could do something like this: See the Pen PwwXvao?editors=0010 by ryan_labar (@ryan_labar) on CodePen. 1
Rodrigo Posted May 13, 2025 Posted May 13, 2025 Hi, In order to complement Ryan's great advice to use a Timeline, you can use the position parameter in order to place the fade-out instance instead of adding an extra Tween in the middle that does exactly what the first Tween does, something like this: const fadeIns = gsap.utils.toArray('.fade'); fadeIns.forEach((fade) => { gsap.timeline({ defaults: { duration: 0.25 }, scrollTrigger: { trigger: fade, markers: true, scrub: true, } }) .to(fade, { autoAlpha: 1, ease: 'sine.in' }) .to(fade, { autoAlpha: 0, ease: 'sine.out' }, "+=0.5") }); Happy Tweening!
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