Jump to content

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

ScrollTriggers do not get placed properly when loading the page from the top, only if refreshed in the middle?

Go to solution Solved by cheestudio,

Recommended Posts

As the title says...I wish I could built a codepen, but it's pretty complicated to isolate. Hoping someone can point me in the right direction. If you load this page: https://svcf.chee.studio/


You'll notice the scroll triggers appear here:






Yet if you refresh the page when you're looking at this section, they appear where they should:








I've tried everything; wrapping in load(), setTimeout(), ScrollTrigger.refresh(),  applying a minimum height to the body and all preceding elements...but it persists! Here's the code as it stands...hoping someone has maybe come across this before and can maybe give me a lead, without having to re-create the whole thing in a CodePen!


$(window).load(function() {
  setTimeout(function() { 
   gsap.utils.toArray(".our-work-image-entry").forEach(function(section, i) {
    copyBlock = section.querySelector('.our-work-copy-entry ');
     trigger: section,
     start: "top 40%",
     end: "bottom 80%",
     pin: copyBlock,
      markers: true,
     onEnter: function() {
     onEnterBack: function() {
  }, 500);


I should also mention this is in Chrome on Windows, but I was able to replicate on FireFox, as well. What's interesting is on FireFox, if I reload the page, it starts working, but the initial load does the same behavior...I assume this is browser caching at work? I have no server-side caching enabled. On Chrome, I can replicate it each time I reload the page when the scroll is at the very top.

  • Like 1
Link to comment
Share on other sites

  • Solution

AH! I found it. The preceding blocks didn't have the correct minimum height.


So, a question: why do I need the minimum height on the preceding elements in the first place, especially when I had this ScrollTrigger wrapped in a load() function?

Link to comment
Share on other sites

ScrollTrigger automatically listens for the "load", "DOMContentLoaded", "resize" and "visibilitychange" events and calls its ScrollTrigger.refresh() method when they occur. That's when ScrollTrigger does all the hard work of calculating the start/end values (where your markers show up). If you're lazy-loading things that mess with the layout, for example, it could throw off all those calculations. Let's say the page loads (initially) and elementA is 100px from the top and ScrollTrigger calculates that as the start position. Cool. But now if an image loads in (or if you've got a framework that's messing with the DOM in a way that's make it reflow) so that suddenly that takes up a bunch of space at the top and shoves elementA down another 500px, ScrollTrigger doesn't know that. 


So in that case, you'd need to call ScrollTrigger.refresh() to have it update things. 


My guess is that when you set minimum heights, you were essentially working around the reflowing that was happening with some kind of images loading or a framework shifting things around AFTER the normal "load" event fired. 


So the two fixes are to either make sure you set proper dimensions on things so that they don't reflow after the page loads -OR- just make sure you call ScrollTrigger.refresh() AFTER you're done shifting the DOM around (reflow). 


Does that clear things up? 

  • Like 1
Link to comment
Share on other sites

Very much so, and what I suspected. I imagine everything you wrote applies if I am using GSAP to animate a bunch of items above it, using X and Y animations? That's all that I had prior to this scroller element that would have shifted. I guess I somewhat assumed GSAP would be aware of that and adjust accordingly, but hell, it already does so much for me! 🤣

Link to comment
Share on other sites

I didn't quite follow that comment about GSAP being aware of x and y animations you were performing. 


Let me clarify...


ScrollTrigger maps out its start and end values (when the scrollbar hits certain values) initially so that it can be SUPER fast during scroll. Scrolling is very performance-sensitive, so it would be TERRIBLE for performance if it had to constantly check getBoundingClientRect() on every tick to check where every trigger is at continuously. Even if you're using GSAP to do animations, there's no way it could possibly map everything out dynamically and know, for example, that if elementA is animating x with an elastic ease and y with different timing/easing and if the user scrolls to a certain position at a certain time, that's where it should trigger. WAAAAY too much processing (and kb of code necessary to do something like that). 


Remember, GSAP and ScrollTrigger place a tremendous priority on performance.  

Link to comment
Share on other sites

It's OK, I'm not explaining it well enough and I don't expect you to dig into my code. I understand GSAP's angle on it, and I'm aware that it's nothing wrong with the core framework/functionality. We're good now!

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