Jump to content
Search Community

Additions to DOM affecting initial ScrollTrigger Positions

pmascis test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Hi All,

 

I've had this occur a few times now, where something gets added to the DOM and the ScrollTrigger positions are now incorrect/out of alignment.

 

Here is one of the more easy to follow (I hope) examples of where/how this problem exists for me.

(Sorry for the lack a codepen and for the lack of of labels in the screenshots, this was taken from a site in production).

The white bar at the top (Frequently asked questions etc.) is a navigational anchor bar which gets pinned to the top of the page.

It is to stop pinning as soon as it touches the grey footer.

 

I have the ScrollTrigger set up correctly to the point where it works most of the time.

However, note that in this screenshot the blue reCAPTCHA box has loaded.

 

01.thumb.png.48c8e9e4986d843c8305ee4cda97fd5c.png

 

 

Now, once this has loaded, the Scrolltrigger is now in an incorrect position.

You can see in the screenshow below, the white bar starts scrolling past the top of the window prematurely, the same height difference as the reCAPTCHA box.

 

02.thumb.png.4fe33e2d8a4352eb7d903712d1cc4665.png

 

I had tried putting my ScrollTriggers in a function that fired on document ready and window.load (even though I'd rather that not be the case), but it doesn't seem to even help.

$(document).ready(anchorNavigationBarScrollTriggerCreate);  /  $(window).on('load', anchorNavigationBarScrollTriggerCreate);

 

Not that it really helps me, but just worth mentioning, once I resize the window ScrollTrigger recalcuates things and the ScrollTrigger is realigned to the correct position as it is now aware of this new DOM element.

 

This is becoming a more frequent problem for me as in other sections of this current website I am pulling in data in the form of an iframe (which is unavoidable), this iframe is quite tall/long too, so all of my nice animations below are all out of whack and really cause some major issues.

 

If anyone can please let me know a possibile solution or let me know if I'm doing something dumb/wrong it would be greatly appreciated, thanks!

 

Paul

 

 

Link to comment
Share on other sites

  • Solution

Hey Paul!

 

Sure, all you need to do is call ScrollTrigger.refresh() after you've made the changes that affect layout. That tells ScrollTrigger to recalculate all the start/end positions accordingly. 

 

Why doesn't it do all that automatically? 

  1. Animation and scrolling are two of the most performance-sensitive things in the browser. We've built ScrollTrigger to be extremely performant. That's why it does all of its calculations up-front (in ScrollTrigger.refresh()) and then every time you scroll it simply has to compare the current scroll position to two values (start/end) for each ScrollTrigger. That's MUCH faster than calling getBoundingClientRect() for each element on every scroll event. 
  2. If ScrollTrigger had to watch every element in the DOM to try to sense when something shifts, that'd kill performance too.
  3.  It's far, FAR better to just have the developer call ScrollTrigger.refresh() when they know their resizing/reflow is done.

If you still need some help, please provide a minimal demo and we'd be happy to take a peek. 

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

Hi Jack, I hope you are well.

 

Thank you for your prompt reply and detailed response, that all makes sense.

To get me out of a this quick jam, I just fired it a second later, which is good enough for now.

function scrollTriggerRefresh () {
  ScrollTrigger.refresh();
}
setTimeout(scrollTriggerRefresh, 1000);

Later on I will work on solutions to refresh at a more specific/appropriate time.

Thanks again!

Link to comment
Share on other sites

Sounds good. I'm not sure why you'd need to wait a second unless maybe you're loading an image and it takes time? Basically, once you make your DOM changes that affect layout, you can instantly call ScrollTrigger.refresh(). 

 

Here's a GSAP way to delay that call by 1 second (setTimout() isn't synchronized with requestAnimationFrame whereas GSAP is):

gsap.delayedCall(1, ScrollTrigger.refresh);

 

  • Thanks 1
Link to comment
Share on other sites

This was just a lazy work around for now, but in my screenshot example, the reCAPTCHA code in the form is what was loading some milliseconds after the document had loaded so 1 second was good enough to wait for it and then fire afterward.

 

I didn't know about delayedCall either, so thank you for that I will give it a go and read about it more in the docs.

Thanks again!

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