Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Most Common ScrollTrigger Mistakes


| GreenSock
6667

Are you guilty of any of the most common mistakes people make in their ScrollTrigger code?

Note: There's also a separate article that covers the most common GSAP mistakes

Creating to() logic issues

If you want to animate the same properties of the same element in multiple ScrollTriggers, it’s common to create logic issues like this:

gsap.to('h1', {
  x: 100, 
  scrollTrigger: {
    trigger: 'h1',
    start: 'top bottom',
    end: 'center center',
    scrub: true
  }
});

gsap.to('h1', {
  x: 200, 
  scrollTrigger: {
    trigger: 'h1',
    start: 'center center',
    end: 'bottom top',
    scrub: true
  }
});

Did you catch the mistake? You might think that it will animate the x value to 100 and then directly to 200 when the second ScrollTrigger starts. However if you scroll through the page you’ll see that it animates to 100 then jumps back to 0 (the starting x value) then animates to 200. This is because the starting values of ScrollTriggers are cached when the ScrollTrigger is created.

To work around this either use set immediateRender: false (like this demo shows) or use .fromTo()s for the later tweens (like this demo shows) or set a ScrollTrigger on a timeline and put the tweens in that timelines instead (like this demo shows).

 

Nesting ScrollTriggers inside multiple timeline tweens

A very common mistake is applying ScrollTrigger to a bunch of tweens inside a timeline. This doesn’t make much sense because both the timeline and the ScrollTrigger would try to control the tweens' playhead. 

It's best to apply a ScrollTrigger to either a standalone tween or to a parent timeline.

 

Using one ScrollTrigger or animation for multiple "sections"

If you want to apply the same effect to multiple sections/elements so that they animate when they come into view, for example, it's common for people to try to use a single tween which targets all the elements but that ends up animating them all at once. For example:

Since each of the elements would get triggered at a different scroll position, and of course their animations would be distinct, just do a simple loop instead, like this:

 

Forgetting to use function-based start/end values for things that are dependent on viewport sizing 

For example, let's say you've got a start or end value that references the height of an element which may change if/when the viewport resizes. ScrollTrigger will refresh() automatically when the viewport resizes, but if you hard-coded your value when the ScrollTrigger was created that won't get updated...unless you use a function-based value.  

end: `+=${elem.offsetHeight}` // won't be updated on refresh

end: () => `+=${elem.offsetHeight}` // will be updated

Additionally, if you want the animation values to update, make sure the ones you want to update are function-based values and set invalidateOnRefresh: true in the ScrollTrigger.

 

Start animation mid-viewport, but reset it offscreen

For example try scrolling down then back up in this demo:

Notice that we want the animation to start mid-screen, but when scrolling backwards we want it to reset at a completely different place (when the element goes offscreen). The solution is to use two ScrollTriggers - one for the playing and one for the resetting once the element is off screen.

 

Creating ScrollTriggers out of order

If you have any ScrollTriggers that pin elements (with the default pinSpacing: true) then the order in which the ScrollTriggers are created is important. This is because any ScrollTriggers after the ScrollTrigger with pinning need to compensate for the extra distance that the pinning adds. You can see an example of how this sort of thing might happen in the pen below. Notice that the third box's animation runs before it's actually in the viewport.

To fix this you can either create the ScrollTriggers in the order in which they are reached when scrolling or use ScrollTrigger's refreshPriority property to tell certain ScrollTriggers to calculate their positions sooner (the higher the refreshPriority the sooner the positions will be calculated). The demo below creates the ScrollTriggers in their proper order.

 

Loading content dynamically but not refreshing

All ScrollTriggers get setup as soon as it's reasonably safe to do so, usually once all content is loaded. However if you're loading content dynamically (via AJAX/fetch/etc.) and that content affects the layout of the page you usually need to refresh ScrollTrigger so it updates the positions of the ScrollTriggers. You can do that easily by calling ScrollTrigger.refresh() in the callback for your method that is loading the new content.

 

Why does my "scrub" animation jump on initial load? Or my non-scrub animation start playing?

Most likely the ScrollTrigger’s start value is before the starting scroll position. This usually happens when the start is something like "top bottom" (the default start value) and the element is at the very top of the page. If you don’t want this to happen simply adjust the start value to one that’s after a scroll position of 0.

 

Tip: How to make "scrub" animations take longer

The duration of a "scrub" animation will always be forced to fit exactly between the start and end of the ScrollTrigger position, so increasing the duration value won't do anything if the start and end of the ScrollTrigger stay the same. To make the animation longer, just push the end value down further. For example, instead of end: "+=300", make it "+=600" and the animation will take twice as long. 

If you want to add blank space between parts of a scrubbed animation, just use empty tweens as the docs cover.


 

Still need some help?

The GreenSock forums are the best place to get your questions answered. We love helping people develop their animation superpowers. 

  • Like 4

Get an all-access pass to premium plugins, offers, and more!

Join the Club

When is the last time you worked on something you love? Go animate something cool and then share it with us.

- Team GreenSock


User Feedback

Recommended Comments

There are no comments to display.



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

×