Jump to content
Search Community

ScrollTrigger in iOS

s94QREspJB test
Moderator Tag

Recommended Posts

Hi all,


we recently did a project with a scroll trigger that creates an endless scroll behaviour. See attached codepen for the markup. Therefore, we need the callbacks of onLeave and onLeaveBack to trigger immediately, also while scrolling: as soon as its marker is hit, the scroll position is updated to either top or bottom 0 values. It works fine on all desktop browsers but not in Safari. It kinda "waits" until the scroll is finished and only then navigates.

This means the scrolling stops for a sec, updates the values and then the user has to start scrolling again. Ideally, this should be one fluid motion. Did anyone ever encounter this issue and knows some way to fix this? We think it might be Safari's easing of the scroll that interferes. I'm not sure if you guys can see this in the CodePen example cuz this seems to work just fine. We think this is due to the fact that the interface does not change when scrolling is happening, e.g browser bar moves in and out. So here is the production website https://dev.mensingtimofticiuc.com as well.

 

Thankful for any hints or tipps and thanks in advance!

See the Pen ZEaXrKx by spar-nation-alleluia (@spar-nation-alleluia) on CodePen

Link to comment
Share on other sites

15 hours ago, s94QREspJB said:

Did anyone ever encounter this issue and knows some way to fix this? We think it might be Safari's easing of the scroll that interferes. I'm not sure if you guys can see this in the CodePen example cuz this seems to work just fine. We think this is due to the fact that the interface does not change when scrolling is happening, e.g browser bar moves in and out.

 

Safari is just a super difficult browser to work with, and there probably isn't a good solution. We spent several weeks trying to solve issues dealing with the address bar on iPhones and couldn't find a way to prevent it from resizing. iPads isn't an issue, just iPhones. 

 

Link to comment
Share on other sites

3 hours ago, OSUblake said:

 

Safari is just a super difficult browser to work with, and there probably isn't a good solution. We spent several weeks trying to solve issues dealing with the address bar on iPhones and couldn't find a way to prevent it from resizing. iPads isn't an issue, just iPhones. 

 

Yeah, that's so. We found some workarounds, though. What we did was to set the height of the html and body elements to 100% and prevent the body element from overflowing. Then, instead set its child (or the one with all your content) to overflow: auto and also set it's height to 100%. This way, you can prevent the address bar from moving in and out. There are some other articles on that topic that I discovered in the forum here. I will link that here just in case they could help someone. First, there is CSS Tricks with an overview and then Matt Smith with a WebKit solution.

Not tested though but will do that now since we encountered another issue: the markers of the trigger scroller-start and scroller-end, seem to react to the actual scrolling. They flicker and move up and down quickly by about 50px or so. This might be the reason for why the scroller does not work reliably on mobile browsers (issue encountered on all mobile browsers). Maybe that's just due to the way I implemented this. Will keep this thread updated, though.

Link to comment
Share on other sites

6 minutes ago, s94QREspJB said:

We found some workarounds, though. What we did was to set the height of the html and body elements to 100% and prevent the body element from overflowing. Then, instead set its child (or the one with all your content) to overflow: auto and also set it's height to 100%. This way, you can prevent the address bar from moving in and out.

 

Yeah, we looked at that too, but we can't use a nested scroller for what we're doing. You'll see in the next release of GSAP, which has a lot of new scrolling features and improvements. Stay tuned 😉

 

Link to comment
Share on other sites

Update: after implementing and testing the code suggested in the articles above it seems again that only setting the body element to overflow: hidden and it's child to overflow: auto (as described in my post above) helps to prevent viewport height changes. This can't be the solution, though, because the markers flicker in their position and are not fixed as you would expect it from desktop experiences. Is there something that can be done here? See the screen cast on iOS 15.3.1 on Safari here: https://drive.protonmail.com/urls/YMTBPAXHZW#tLm15WgQq1QO

Additionally, if none of the options described in this thread are applied, the scroll trigger does resize but only once the user has finished scrolling. This does not work reliably as it should happen immediately after the viewport changes. Is there some option or function to tell the scroll trigger to resize immediately rather than waiting for the scroll to finish? See the screen cast for this issue on iOS 15.3.1 on Safari here: https://drive.protonmail.com/urls/A1FCWDTY44#qyesN99JRMP3

 

The code is in both cases the same as in the OP, instead of changing the scroller for option 1 to the overflowing child container like so (done with Vue.js v2.6.12):

 

this.scroller = document.getElementById('scroller');
createScrollTrigger() {
// ...
this.scrollTrigger = ScrollTrigger.create({
scroller: `#scroller`,
// ...
},

Pen posted again here for the sake of completion:

 

Greatly appreciating any help and thanks in advance!

Link to comment
Share on other sites

20 hours ago, s94QREspJB said:

the markers flicker in their position and are not fixed as you would expect it from desktop experiences. Is there something that can be done here?

iOS Safari has quite a few glaring bugs related to scrolling.

 

You might want to look into the brand new ScrollTrigger.normalizeScroll() as well as the new:

ScrollTrigger.config({ ignoreMobileResize: true });

And try the new 3.10.0. See if it improves anything for you, especially by activating the normalizeScroll() feature.

 

Markers are only for during development anyway, so I wouldn't worry too much if they jitter since you'll remove them.

 

20 hours ago, s94QREspJB said:

Additionally, if none of the options described in this thread are applied, the scroll trigger does resize but only once the user has finished scrolling. This does not work reliably as it should happen immediately after the viewport changes

This was very intentional, actually. If the ScrollTrigger.refresh() occurs during the momentum scroll, it'll suddenly stop it. Not because ScrollTrigger is asking it to, but because if there's any setting of the scroll position whatsoever, the browser assumes it should stop. Therefore, we specifically added code to wait until the momentum scroll is done before triggering the refresh(). So it's a feature, not a bug :)

 

You can definitely force a ScrollTrigger.refresh() anytime you want. Like in a "resize" event handler. You can also use ScrollTrigger.config() to have ScrollTrigger not refresh() automatically on window resizes at all if you prefer to handle that on your own (change autoRefreshEvents). It's super flexible.  

 

Does that help at all? 

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

Hello there!

 

Quote

And try the new 3.10.0. See if it improves anything for you, especially by activating the normalizeScroll() feature.

 I tried this but unfortunately, it does not fix our problem. Resizing due to the address bar transitioning in and out still takes place. In my understanding, normalizeScroll() is a method you'd use on the whole instance of your Scroll Trigger, therefore I placed it beaneath the actual initialization. Not sure if it does something now. Also, if I store the instance in a variable and use it like so this.scrollTrigger.normalizeScroll(), it's throwing an error saying that normalizeScroll() is not a function. Does this only work globally on all instances?


If this implementation is correct, the problem could still persist due due to the fact that we're on the latest iOS which was pointed out to not work with normalizeScroll(). Seen in the docs with:

Quote

One exception we know of is the most recent version of iOS, only on phones in portrait orientation where the browser forces the show/hide (it seems impossible to work around, but you can still use ScrollTrigger.config({ ignoreMobileResize: true}) to skip refreshes in that case). 


I then tried ignoreResize: true as a config parameter which also does not seem to change anything. In the updated pen attached, you will find the way I implemented both methods. Might be that I missed something.
 

 

Due to these (to me) unresolvable issues, I reverted back to the code to make it at least work. I found that on mobile, the trigger does not work at all anymore. Pen reflects current code. Does anyone know why this is the case? In CodePen, it does work just fine. This is the link to the screen capture of the live project to help you understand the problem: https://drive.protonmail.com/urls/3W8WQVTPXM#GcTSjdGcPQkv

 

Thanks for your help guys and have a nice day!

Link to comment
Share on other sites

On 4/6/2022 at 1:55 AM, s94QREspJB said:

normalizeScroll() is a method you'd use on the whole instance of your Scroll Trigger, therefore I placed it beaneath the actual initialization. Not sure if it does something now. Also, if I store the instance in a variable and use it like so this.scrollTrigger.normalizeScroll(), it's throwing an error saying that normalizeScroll() is not a function. Does this only work globally on all instances?

Yes, you just call the static ScrollTrigger.normalizeScroll(true) function and it applies special behavior to the scrolling of the root/body only. It is NOT a per-ScrollTrigger instance setting. 

 

Your CodePen breaks because you're using an old version of ScrollTrigger that doesn't have normalizeScroll() :)  You need to use the latest version (3.10.2 as of right now). I bet that's why you didn't notice any difference with this line too: 

ScrollTrigger.config({ ignoreMobileResize: true });

That won't do anything if you're not using 3.10.x+

 

Side note: I noticed you're setting syncInterval: 999999999 on the ScrollTrigger.create() config, but that won't do anything. That's a ScrollTrigger.config() setting that's global. Again, it won't hurt anything to have it where you do - it simply gets ignored. 

 

Lastly, I looked at your demo on my iPad and I didn't notice any strange behavior at all - what are the symptoms I should be looking for? How exactly is it breaking? Does it only happen on iPhones? Does it work again if you revert to 3.9.0? 

  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...

Alright, thx for clarifying!

I did disable the syncInterval now as it did not seem to make any difference, even with the correct implementation. normalizeScroll() set globally did stop the scrolling from working. The user could not scroll at all. I was unable to find out why this is the case. If it matters: we are developing on Vue.js v.2.6. Might be that the threading is mixed up somehow? :huh:


Oh, sure! I did not use the latest version of GSAP in the Pen but have the latest as of now in use in my project. We did change the code to make it work again. Therefore we removed the conditions with isLopping int he callbacks. If I do this in the pen, it stops working however because then both triggers are called at the same time. In (most) of the browsers, it works fine, though.

 

Quote

Lastly, I looked at your demo on my iPad and I didn't notice any strange behavior at all - what are the symptoms I should be looking for? How exactly is it breaking? Does it only happen on iPhones? Does it work again if you revert to 3.9.0? 

Did you look at the pen on your iPad or the actual link of the project I provided? If it was the latter, could you try it again now that we've updated the code? It works fine but sporadically stops scrolling as it reaches top or bottom of the page. It should, just as before keep on scrolling due to the endless scroll we implemented. It happens on all mobile browsers and also on iOS as well as Android (at least that's what I tested with browserstack) and the GSAP version does not matter. It happens all the same.

 

Here's the link of the project again and this is a screen cast of what I mean.

Link to comment
Share on other sites

I suspect the non-infinite scroll issue is caused by the fact that you're setting the start/end to the VERY top and bottom which doesn't always let it actually hit or exceed - I would use a 1 pixel threshold like: 

start: 1,
end: () => ScrollTrigger.maxScroll(window) - 1,

Some browsers report scrolling values as very slightly off, thus you're giving yourself a little wiggle room to cover over those inconsistencies. 

Link to comment
Share on other sites

  • 1 year later...

Hello GSAP team,

 

thanks again for your awesome library!

 

May I jump in here regarding the iPhone scroll issues?

 

On this page: https://greensock.com/docs/v3/HelperFunctions#getScrollLookup we have the Stop iOS Safari from resizing the window on scroll section.

 

1) is this supposed to work, though? In my case it caused all kinds of unexpected behavior, added white spaces on scroll trigger pin sections etc.

(Unfortunately a minimal demo cannot help as my html structure is complex and it might be the reason, too)

 

2) When I have, let’s say a typical kind of Wordpress page structure with internal post main containers etc. can I use those or does the container you describe there need to have the exact naming of “#viewport” (maybe there is something under the hood where it is used as a specific selector?)

 

3) In the very section before Stop overscroll behavior, even on iOS Safari you describe usage of the function. Is this function maybe a necessary requirement to make the CSS code mentioned work? For as I said in my case it destroyed everything.

 

Thanks in advance for clarification!

Best,

Stefan

Link to comment
Share on other sites

16 hours ago, Garavani said:

1) is this supposed to work, though? In my case it caused all kinds of unexpected behavior, added white spaces on scroll trigger pin sections etc.

I'm super curious to see what you're talking about ("all kinds of unexpected behavior, added white spaces, etc."). A minimal demo would be super appreciated. 

 

Since posting that solution, iOS Safari has changed how it handles things in some cases. For example, on phones it's now impossible (as far as I can tell) to completely prevent that resize, at least without losing other significant functionality. Honestly, Safari has just been terrible. Apple has known about significant bugs for years that they haven't bothered to fix, and they've been unresponsive on the many occasions we've tried to reach out. It's pretty shocking and discouraging. 

 

I wouldn't necessarily recommend using that "fix" anymore. I removed it from the helper functions page in the docs now. Have you tried just using ScrollTrigger.normalizeScroll(true)? It can't solve every single problem, but we've invested many hundreds of hours into working around all the various Safari bugs and that's the best we can do at this point. 

 

16 hours ago, Garavani said:

2) When I have, let’s say a typical kind of Wordpress page structure with internal post main containers etc. can I use those or does the container you describe there need to have the exact naming of “#viewport” (maybe there is something under the hood where it is used as a specific selector?)

It doesn't need that exact ID, no. The critical thing is that it must be the very ROOT element. 

 

16 hours ago, Garavani said:

3) In the very section before Stop overscroll behavior, even on iOS Safari you describe usage of the function. Is this function maybe a necessary requirement to make the CSS code mentioned work? For as I said in my case it destroyed everything.

Again, "destroyed everything" is super curious to me. Very difficult to speak to this without any demo. I'm really not sure what to tell you, sorry. If you'd like more assistance, please make sure you provide a minimal demo that clearly shows the issue and we'd be happy to take a peek. 👍

  • Like 1
Link to comment
Share on other sites

Thank you very much for these clarifications! 

Indeed, normalizeScroll (almost) did the job for me. Had some issues after with fixed containers on the start of the page that before weren’t a problem. But I solved them in another way (scroll independent animation at the start).

 

Thanks so much for all the work and the grey hair due to Safari. I can imagine the trouble. Keep on!

Best,

Stefan

Link to comment
Share on other sites

  • 2 months later...
On 3/29/2022 at 12:45 AM, OSUblake said:

 

Safari is just a super difficult browser to work with, and there probably isn't a good solution. We spent several weeks trying to solve issues dealing with the address bar on iPhones and couldn't find a way to prevent it from resizing. iPads isn't an issue, just iPhones. 

 

As you mentioned OSUblake, your issue on dealing with the address bar, I solved it partially using Smooth Scrollbar. As it is not a native scrollbar, it does not produce the viewport resizing.

 

Link to comment
Share on other sites

@Rodrigo Hi! Well, recently I was struggling with a project including gsap and three js, with no smooth scroll in mobile and many images, with a 3d model in the order of 30k polygons. So, it was resizing on mobile scrolling, and producing crashes in iOS. Since I was including Smooth Scrollbar (third party), I tried it on mobile and it worked great! Currently, I am dealing with lag in scrolling in some iOS devices, so I am going to implement the "will-change" workaround, hoping it will work.!

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