Jump to content


Animating between a list of items inside another timeline

Recommended Posts

To start off, I'm going to share an example of the animation I am trying to recreate. The key takeaways are that I want the first element in the list to animate differently than when the list is cycling through itself. This means that I need a one-off animation for the first list item, before it then sequences through a list that should repeat a couple times.


I was able to animate the first list item the way I wanted initially, but the moment I added listTween, the alpha was no longer visible due to the staggerFrom's.


How can I break off the first-one (something like first-of-type) and then cycle it back into the repeated animation thereafter?


The second issue I'm struggling with is that the listTween between repetitions has a delay in which none of the listItems are visible. Is there a better way of setting this up so that they sequence for 5s at a time, but don't delay in repeating the loop?




Edit: I've made some minor tweaks so that my first list item is displaying, but still unsure of how to start the tween at the second list item and then circle back in the first one after it repeats.


See the Pen EvoBdq by ekfuhrmann (@ekfuhrmann) on CodePen

Edited by ekfuhrmann
Updated codepen.
Link to comment
Share on other sites

Hi @ekfuhrmann :)


I've read your question a few times and maybe I'm just tired, but I'm not sure I completely understand what you're asking. Do you think you could trim this demo back to just a few of the words you'd like to animate and what you expect to happen? Generally, the simpler the better. 


Thanks much and happy tweening.


  • Like 1
Link to comment
Share on other sites

Yeah, I'm in the same boat as PointC. I looked at this earlier and had a tough time putting it all together. 

Perhaps we can just focus on one of the issues first in a pen that only has enough assets and code to illustrate that issue. Then we can build from there if other issue persist.

  • Like 1
Link to comment
Share on other sites

Apologies for not being clear the first time, hopefully this makes more sense!


I removed a lot of the unnecessary elements to make it more clear. I also added better comments into the JS to help explain what should be happening throughout the timeline.


What I'm trying to have happen is for the first item in 'marquee__list-item' (tagline one) to have a different animation from the rest of the list items the first time it animates.


Once that animation has passed, I then want to cycle through all of the taglines (tagline two, tagline three, tagline one) with the same animation which just repeats. My issue is that the list tween impacts my tagline one animation on the first pass. It then also has some delays in it between its repetition which makes it really easy to identify where the repeat is for it. That I know I can fix with better timing, but I'm struggling breaking out the first item animation within the list from the repeat tween that I would like to run for all of them.



See the Pen JyLNPE by ekfuhrmann (@ekfuhrmann) on CodePen


Link to comment
Share on other sites

Thanks for the updated demo. I think I understand what you're trying to do.


You have a set of elements that you want to stagger and repeat, but on the first pass, element[0] should not be a part of the stagger, correct? On iteration 1 element[0] is going to do its own animation, but every repeat thereafter it should be a part of the stagger array? 


If that's the case, there would be a number of ways to make this happen. For simplicity I just made a couple new demos with some divs so we can clearly see what's going on. In this first option I have made two arrays. One with all the boxes and one with all the boxes except .box1 using jQuery's .not() selector. You'll see the result is box1 animating its y position on the first tween and boxes 2-5 rotate. After that, all 5 boxes rotate.


See the Pen xLWdap by PointC (@PointC) on CodePen

Another option would be to create the target array and then splice out the first element. You'd then play your first iteration of the animation and onComplete call a function that recreates the array and staggers all the elements in a new stagger tween. It's the same result, but just a different approach.


See the Pen gxeGRQ by PointC (@PointC) on CodePen


Personally, I'd go with the 1st option as it's a bit simpler. The bottom line is you need an element to be part of an array for one stagger animation, but not part of it for another so I think you'll need to create a couple arrays as targets or modify one between animations. Others may have additional ideas better than mine. Hopefully that helps.


Happy tweening.


  • Like 5
Link to comment
Share on other sites

You understood exactly what I was asking, so thank you for that! It goes without saying that you and the rest of the GSAP team are absolutely incredible and helpful, and I can't thank you all enough!


With your provided codepen examples, I was able to get pretty close to the animation I was aiming for; however it seems for every hurdle I jump over, another one comes up.


I have the following timeline:


    .from($marqueeLine, 0.6, {width: 0}, 0)
    .fromTo($marqueeTitle, 0.6, {y: '+=100', autoAlpha: 0}, {y: '100%', autoAlpha: 1}, 0.1)
    .add('endLine', '+=2')
    .add('startList', 'endLine')
    // Animite in tagline[1]
    .from($marqueeListItemFirst, 0.4, {scaleY: '0', autoAlpha: '0', transformOrigin: '100% 100%'}, 'startList')
    // Animate title
    .to($marqueeTitle, 0.3, {y: '0%'}, 'startList')
    // Animate out tagline[1]
    .to($marqueeListItemFirst, 0.4, {autoAlpha: 0, rotationX: '90deg', transformOrigin:'0% 0%'}, 'startList +=5')
    // Animate in the other taglines -- tagline[2], tagline[3] 
    .staggerFrom($marqueeListItemNotFirst, 0.4, {autoAlpha: 0, rotationX: '90deg', transformOrigin:'100% 100%'}, 5, 'start -=0.25')
    // Animate out the other taglines -- tagline[2], tagline[3] 
    .staggerTo($marqueeListItemNotFirst, 0.4, {autoAlpha: 0, rotationX: '90deg', transformOrigin:'0% 0%'}, 5, 'start +=4.65')
    // Animate tagline[1], tagline[2], tagline[3] on loop
    .add(loopListTween, '-=0.3'); // start early so that transition is seamless


Everything animates and is timed correctly up until we get inside  'loopListTween'


var loopListTween = new TimelineMax({repeat: 2});
    .staggerTo($marqueeListItem, 0.4, {autoAlpha: 1, rotationX: '0deg', transformOrigin:'100% 100%'}, 5, 'startListLoop -=0.6')
    .staggerTo($marqueeListItem, 0.4, {autoAlpha: 0, rotationX: '90deg', transformOrigin:'0% 0%'}, 5, 'startListLoop +=4.9');
    // When this finishes repeating, there is a delay between the start and end. How would you remove the delay between repeats?


In the master timeline, I have this loop start 300ms early so that it seamlessly continues from the 'Animate out' tween. This works fine initially, but then does not work once within the loop, causing there to be a couple hundred MS delay between when the loop ends and the next iteration begins.


Any suggestions on what I can do there? Or suggestions to make this timeline more manageable?


Updated codepen can be found below.


See the Pen JyLNPE by ekfuhrmann (@ekfuhrmann) on CodePen



I should also mention that while your codepens were super helpful in getting me to this point, 'autoAlpha' has proved a real pain to manage as it seems that the later tweens using it override the earlier ones. This is what has lead to my 'loopListTween' having two 'staggerTo' tweens rather than the 'staggerFrom' and 'staggerTo' tween I used earlier for the partial cycle.


Again, thank you for the time you've put towards helping me. I've learned a whole lot through this process so far.

Link to comment
Share on other sites

Your loopListTween timeline works with the negative relative overlap on the first pass because it's playing after a different timeline. It sounds to me like you're trying to loop that timeline with a negative overlap on itself? If that's the case, that won't work. The playhead of a timeline can only be in one place at a time. You can't start the timeline again while it's still playing to the end. Does that make sense?


If that's what you want, your best option (IMHO) would be to create individual tweens/timelines for those elements in a loop and then you can overlap them all you want. The first element can be starting its second iteration before the last element has finished thus giving you a seamless loop.


I'm not sure I understand the autoAlpha part of your question, but you may have tweens overwriting other tweens. I didn't go too deep into your pen, but you've got a lot of relative offsets to the tween start times so that's certainly possible. You may have to adjust those times or set the overwrite to none. More info about that:



Hopefully that helps. Happy tweening.


  • Like 3
Link to comment
Share on other sites

  • 3 weeks later...

@PointC, I get what you're saying about placing the tweens into their own individual timelines, but I'm really struggling with how to achieve that within this project. I've made a mess of a forked codepen trying to get something remotely resembling what you suggested but to no avail.


I looked at some other nested codepens but the ones I have found tend to be hover animations, rather than a looping list of names.


Any suggestions?

Link to comment
Share on other sites

You can use a regular loop or something like jQuery's each() method. Here's a quick example:


See the Pen YrKLRg by PointC (@PointC) on CodePen

See how box1 is starting its repeat before box3 has finished its first play? Using the index of the element, you can set delays for each timeline. With each element now playing on its own timeline, you have a lot of control and can create seamless loops.


Hopefully that makes sense. Happy tweening.


  • Like 1
  • Thanks 2
Link to comment
Share on other sites

This was helpful and I'm definitely getting closer.


Building off of your Codepen I modified it slightly to better reflect the issue I'm running into.


See the Pen BwBGoJ?editors=1010 by ekfuhrmann (@ekfuhrmann) on CodePen


Since it's building the timeline each time for the list, it's overriding the prior element and ends up only looping the final iteration of the list. I'm probably missing something simple here to get this working.


Link to comment
Share on other sites

You just need to move the line that adds the tween timelines to the loop timeline. Right now you have that outside of the each() loop so the only one that gets added is the third one which is why that's the only one that repeats. Move that line into the loop so they all get added and I think you'll get the desired behavior.


See the Pen wrvMXw by PointC (@PointC) on CodePen

Hopefully that helps. Happy tweening.


  • Like 2
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.