Jump to content
Search Community

ScrollTrigger with snap sections but only for part of webpage

fdev test
Moderator Tag

Recommended Posts

Can someone please help me as I want to use the scroll snap effect but I don't want it on the whole webpage. So you can see in my codepen which I took from a different forum you cant actually land on the white sections they just get scrolled past.

 

If you scroll up from the blue section you will see the white section I built.

 

I also made one at the bottom which you can't even scroll to.

 

Thanks

See the Pen ZEVqooz by fayskerritt (@fayskerritt) on CodePen

Link to comment
Share on other sites

Hi,

 

I think the issue stems from this:

ScrollTrigger.create({
  // start: 'top top',
  // end: 'bottom bottom',
  markers: true,
  snap: {
    snapTo: (progress, self) => {
      let panelStarts = tops.map((st) => st.start), // an Array of all the starting scroll positions. We do this on each scroll to make sure it's totally responsive. Starting positions may change when the user resizes the viewport
        snapScroll = gsap.utils.snap(panelStarts, self.scroll()); // find the closest one
      return gsap.utils.normalize(
        0,
        ScrollTrigger.maxScroll(window),
        snapScroll
      ); // snapping requires a progress value, so convert the scroll position into a normalized progress value between 0 and 1
    },
    duration: 0.5
  }
});

That's a ScrollTrigger without any trigger element, so ScrollTrigger defaults to the viewport.

 

If you want to pin and snap just in a specific section, then do that on a ScrollTrigger instance that applies only to that particular section. Also be sure that the ScrollTrigger instances are created in the order they appear in the screen.

 

I'd strongly recommend you to create just the ScrollTrigger instance for that particular section, then add the other ScrollTrigger instances to your page, in order to isolate that and get it working as expected.

 

Finally in this cases when you have a bunch of instances is better to add specific ids in order to identify each ScrollTrigger instance and you can even add indentation to the markers:

ScrollTrigger.create({
  id: "one",
  markers: true,
});

ScrollTrigger.create({
  id: "two",
  markers: {
    indent: 200,
  },
});

That will create distinctive markers for each section and that will allow you to debug easily.

 

Hopefully this helps.

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Can I please add to this conversation and ask if it is possible to snap elements so that the top is 100px from the top of the viewport (for example so the element snaps so the top meets the bottom of the navbar).

 

At the moment the element is going right to the top of the viewport so some of it is hidden beneath the navbar.

 

Thanks

Link to comment
Share on other sites

2 hours ago, fdev said:

Can I please add to this conversation and ask if it is possible to snap elements so that the top is 100px from the top of the viewport (for example so the element snaps so the top meets the bottom of the navbar).

 

At the moment the element is going right to the top of the viewport so some of it is hidden beneath the navbar.

Yes, that sounds like something that's possible. If you need some help, please show us what you tried in a minimal demo (like a CodePen). Context is really key in a case like this. You can apply your own snapping logic in whatever way you want by using a function-based snapTo value. 👍

Link to comment
Share on other sites

@fdev the problem is that you set things up in a way that'd have the ScrollTriggers overlap with each other. I think you're only considering the "start" but forgetting that there's an "end" for each ScrollTrigger, and when you set snap: 1, that means that it'll snap to either the start or the end. But you've got ScrollTriggers with ends that are past the start of previous ones. ScrollTrigger is doing what it's supposed to do, but there's just a logic flaw in your code/setup. 

 

If your goal is to only factor in the start of each section, I'd take a totally different approach: 

See the Pen PoXrNVW?editors=0010 by GreenSock (@GreenSock) on CodePen

 

Basically create an Array of ScrollTriggers purely for tracking the scroll position of each panel, and then create a single ScrollTrigger that handles all of the snapping based on those positions. 

 

I hope that helps. 

  • Like 1
Link to comment
Share on other sites

This is really thank you!

 

One more question, is there any way to speed the snap up, it doesn't seem to have the same layout as a timeline so not sure if its as easy as adding 'duration: 0.2' or something like that?

 

I just want it to snap a bit quicker than it does currently if possible.

 

Thanks

 

Sorry also to add to this, in the minimal demo the Orange section is bigger than 100vh so once the top of this section has reached the top is there a way like before allowing it to be normally scrolled until the next section reaches the viewport then to snap to that?

Link to comment
Share on other sites

Hi,

 

6 hours ago, fdev said:

One more question, is there any way to speed the snap up, it doesn't seem to have the same layout as a timeline so not sure if its as easy as adding 'duration: 0.2' or something like that?

Sure thing, you can tap into snap advanced config in order to set it up the way you want (scroll down to the snap section of the config):

https://gsap.com/docs/v3/Plugins/ScrollTrigger/#config-object

 

6 hours ago, fdev said:

Sorry also to add to this, in the minimal demo the Orange section is bigger than 100vh so once the top of this section has reached the top is there a way like before allowing it to be normally scrolled until the next section reaches the viewport then to snap to that?

Same thing, you'll have to create your own custom logic in the snap config. In order to set a duration of the snap and also add this type of functionality you have to do something like this:

ScrollTrigger.create({
  trigger: element,
  start: "top top",
  end: "+=200",
  snap: {
    duration: {min: 0.2, max: 0.3},
    snapTo: (value) => {
      // Creat your custom logic here for your specific snap values
    },
  },
});

Another option is to create a custom array of snapping values and pass that array to snapTo

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

9 hours ago, fdev said:

I just want it to snap a bit quicker than it does currently if possible.

Not really - ScrollTrigger can't do its snapping until the native scroll completely STOPS, otherwise it would interfere with the user doing their own scrolling. So even if you set the delay to 0, that isn't entirely possible because it still has to wait for native scrolling to totally stop. 

Link to comment
Share on other sites

 

1 hour ago, GreenSock said:

Not really - ScrollTrigger can't do its snapping until the native scroll completely STOPS, otherwise it would interfere with the user doing their own scrolling. So even if you set the delay to 0, that isn't entirely possible because it still has to wait for native scrolling to totally stop. 

 

Thanks for clarifying, this makes sense!

 

In regards to getting the scroll to not snap when the panel is taller than 100vh where would I put this logic in the demo that you sent Jack as I am struggling to figure it out in the function in the demo below:

 

See the Pen BavgEzG by fayskerritt (@fayskerritt) on CodePen

 

 

Link to comment
Share on other sites

Hi,

 

It has to go in the snap function you have here:

ScrollTrigger.create({
  // you can add a trigger and start/end values if you'd like to limit the snapping to only part of the page. 
  snap(progress, self, direction) {
    let totalDistance = self.end - self.start,
        snapProgress = snaps.map((v) => v / totalDistance);
    return ScrollTrigger.snapDirectional(snapProgress)(progress, self.direction);
  }
});

In that function you have to return a progress value (between 0 and 1) where ScrollTrigger will eventually land the scroll position. That's what you'll have to figure out based on the points you want your ScrollTrigger instance to snap.

 

Happy Tweening!

Link to comment
Share on other sites

Hey, 

 

Sorry to keep asking questions but I have read through the docs again and again and can't seem to figure out how to stop the snap happening midway through a section if the section is more than 100vh.

 

I tried to debug and console logged the progress for each section to figure out where snapProgress was coming from but can't figure out how to stop the snap being triggered until you get to the bottom of the section. I tried changing 'start: "bottom bottom" but this then snaps to the bottom of the section instead of the top:

 

See the Pen BavgEzG by fayskerritt (@fayskerritt) on CodePen

 

Thanks for your advice before, but can you please point me towards which bit of the scroll function I need to edit to stop this from happening as I tried changing the return to values but this broke the function altogether.

 

Thanks

Link to comment
Share on other sites

Hi,

 

This is a simple example of using the custom snap functionality:

See the Pen OJdLbme by GreenSock (@GreenSock) on CodePen

 

Basically you check the value passed by the snapTo callback and if t matches certain criteria you can return a specific value, a specific value from an array or calculation or null if you don't want any snapping at all.

 

Is worth noticing that using snap as a function works in the same way, sans the extra configuration properties in it:

scrollTrigger: {
  trigger: ".wrapper",
  start: "top top",
  end: "+=" + (100 * panels.length) + "%",
  pin: true,
  scrub: true,
  snap (value) {
    if (value > 0.15 && value < 0.35) {
      return 0.25;
    }
    if (value > 0.65 && value < 0.85) {
      return 0.75;
    }
    return null;
  },
}

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

  • 4 months later...

Hey guys, I am having an issue when applying start and end values to the ScrollTrigger so that the snapping effect happen only to certain part of the page. 

the snapping suddenly stops working like it did before I assign start/end values, and snaps to random values for each panel of the array 

I tried adding some padding to the container so the markers would not intertwine but it didn't help.

 

here is a minimal demo

See the Pen yLrywma by hmdpenning (@hmdpenning) on CodePen


 

ideal state would be that the snapping happens when top of the panels container reaches bottom of screen, and ends when its bottom reach bottom of the screen.

Link to comment
Share on other sites

To explain the snap values. It snaps to a progress value of the ScrollTrigger where 0 is the start and 1 is the end. I have no idea what your snapper ScrollTrigger is doing, but is seems rather complicated. I've now just set a snap to all your ScrollTriggers to 1 eg only snap to the end of each ScrollTrigger. Now only on page load there is no snapping to the first section so you could add one extra ScrollTrigger that tackles that. 

 

If you want you can debug your snapping ScrollTrigger by logging the value it gets you when scrolling and then you can see if that is correct with your logic, but it is really hard to map some distance to a value between 0 and 1, it is better to just use the ScrollTriggers them self. Hope it helps and happy tweening! 

 

See the Pen RwOPbEV?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

Link to comment
Share on other sites

3 hours ago, mvaneijgen said:

To explain the snap values. It snaps to a progress value of the ScrollTrigger where 0 is the start and 1 is the end. I have no idea what your snapper ScrollTrigger is doing, but is seems rather complicated. I've now just set a snap to all your ScrollTriggers to 1 eg only snap to the end of each ScrollTrigger. Now only on page load there is no snapping to the first section so you could add one extra ScrollTrigger that tackles that. 

 

If you want you can debug your snapping ScrollTrigger by logging the value it gets you when scrolling and then you can see if that is correct with your logic, but it is really hard to map some distance to a value between 0 and 1, it is better to just use the ScrollTriggers them self. Hope it helps and happy tweening! 

 

 

 

Hey. thanks for the demo, I am not sure why but sometimes it is skipping random panels when they scroll into view, and I'm curious how I can use the demo with the normalized snap values in a seperate scrolltrigger as they actually worked pretty much how I wanted it, except it started snapping before the snappable sections scrolled in view.


and it only messed up when I assigned a trigger, plus the start/end values to the second ScrollTrigger (the one with snapTo) so I didn't think the values would be the reason it stopped working.

 

I tried debugging it here with logging the normalized value and its components (min, max, snapScroll) before and after assigning a trigger, those values stay the same, yet the calculated normalizd value changes. 

 

See the Pen yLrywma?editors=0011 by hmdpenning (@hmdpenning) on CodePen


 

Link to comment
Share on other sites

9 hours ago, h-amad said:

is Progress in 

snapTo(progress, self)

being used here, or can we remove it? 

It's not being used in our calculation, but I'm not sure what you mean by "remove it". You can't really do that because we're using the "self" parameter, so you need a placeholder there. See what I mean? Or did I misunderstand your question? 

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