Jump to content
Search Community

choosing the right pinType for desktop and mobile with ScrollSmoother

RJWadley test
Moderator Tag

Recommended Posts

ScrollSmoother works really well in a desktop environment, but I've run into some issues trying to adapt pinning code to also work well on mobile. I haven't seen anybody on the forum talk about this yet, so I thought I'd share my experience and a solution I've found.

 

On desktop, ScrollSmoother is transforming the entire page, so the default pinType of "transform" works best.

On mobile, ScrollSmoother turns off and the page scrolls normally, so the default pinType causes sync jitter. A pinType of "fixed" would work really well here, but that will only work if we haven't initialized ScrollSmoother at all (since ScrollSmoother leaves a transform behind even when disabled).

Here's an example that works great on desktop, but jitters on mobile: 

See the Pen JjpaaYR by RJWadley (@RJWadley) on CodePen

 

One potential solution here (and the one that most sane people probably choose) is to enable normalizeScroll. That moves scrolling to the JS thread, which fixes the sync jitter. But it's not always a perfect solution (and in all fairness, there is no "perfect" solution, especially with fruit-based devices). Anyway, decided I just wasn't satisfied with it.

 

Another solution is to always use a fixed pin with pinReparent enabled, but that's not ideal for performance and can break styles, so I'd rather keep that as a last resort.

 

In my mind, a better solution is to just not enable scrollSmoother at all on mobile devices, then choosing pinTypes based off of that. In hindsight it's a very obvious solution, but it took me quite a while to figure it out.

A simple util like const usingSmoothScroll = !matchMedia("(hover: none)").matches; can help us determine the device type. And we can use the same util to determine which pin type to use as well:

pinType: usingSmoothScroll ? "transform" : "fixed"

From there, only create a ScrollSmoother instance if usingSmoothScroll is true:

const usingSmoothScroll = !matchMedia("(hover: none)").matches;
if (usingSmoothScroll)
  ScrollSmoother.create({
    smooth: 1,
    smoothTouch: 0.1 //we don't want scrollsmoother to entirely ditch the smooth, that would break our pins
  });

Here's the same example as above, but employing this technique: https://codepen.io/RJWadley/pen/MWVEzVg

We get the buttery goodness of ScrollSmoother on desktop devices, and the firm beauty of fixed pins on mobile.

 

All around a pretty good solution. Keep in mind that if the media query in the util ever changes (like if a 2-in-1 enters tablet mode), nothing will update. And if ScrollSmoother ever picks up the ability to hotswap between smooth and smoothTouch (right now it just picks one and never changes), this would probably need significant changes.

 

I think an overall cleaner solution would a new pinType (maybe "smoother" or "smoother-auto") that uses fixed if smoother is off and transform if smoother is on. In order for that to work, ScrollSmoother would also need to remove any transforms from smooth-content when it disables. But that's entirely up to the gsap devs.

See the Pen MWVEzVg by RJWadley (@RJWadley) on CodePen

Edited by RJWadley
update codepen embed order
Link to comment
Share on other sites

Thanks for the detailed feedback, @RJWadley!

 

Yeah, Apple devices are quite a headache when it comes to scroll; there have been serious bugs for YEARS that they haven't addressed. Super frustrating. 

 

You mentioned normalizeScroll() not being an ideal solution - do you mind sharing more about what caused you to draw that conclusion? 

 

A few other ideas/thoughts:

  • I'll edit the next release of ScrollSmoother to nix that empty transform on the content.
  • You could gsap.set(smoother.content(), {clearProps: "transform"}) right after you create your ScrollSmoother to manually kill that in the meantime.
  • Instead of your usingSmoothScroll variable, you could probably use ScrollTrigger.isTouch === 1 to sense if it's a touch-only device. 

If you nix the transform on the content, does that resolve everything for you? 

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