Jump to content


Snap only if a third or 25% of the screen has been scrolled

Recommended Posts



I'm implementing a very simple example of snap based on this demo

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

The problem is that if directional is set to false I have to scroll half the screen to be snapped to the next section (which is way too long), if directional is set to true, as soon as I scroll up or down I'm snapped to the previous or next section (which is way too short), the ideal would be to decide how much you've been scrolled before the snapping triggers (eg: 25% of the screen).


I've been reading the doc and few other posts on this forum without really finding an exact answer or if it's at least doable.


I start to think that I shouldn't start from the gsap demo and rather think differently, so is there a way to achieve that? Is there another way to approach this?


the js code for the problem starts at line 215.


Thank you.


See the Pen MWXvRyY by romaingranai (@romaingranai) on CodePen

Link to comment
Share on other sites



The point is that snap, is based on the progress of the ScrollTrigger instance and basically will snap such instance to the closest value based on the one passed/returned. Since you have 3 sections you can snap to 0% - 50% - 100%, hence 1/2 kind of works but is kind of absolute.


What you can do is use a function based value in the snapTo property and run some conditional logic to check the current progress and return the corresponding snap value:

  snap: {
    snapTo(self) {
      if (self < 0.25) {
        return 0;
      } else if (self > 0.25 && self < 0.75) {
        return 0.5;
      return 1;
    ease: Expo.easeOut,
    delay: 0,
    duration: {min: 0.5, max: 2},
    directional: false,
    inertia: true

Of course this will work only when scrolling down, if you scroll back up you'll have to use a different conditional logic in order to reverse the elements when scrolling back up 25% of each section, so you should also keep track of the scroll direction. In this code self refers to the value of final progress of the ScrollTrigger instance based on the velocity.


Hopefully this helps. Let us know if you have more questions.


Happy Tweening!

  • Thanks 1
Link to comment
Share on other sites

Hi @Rodrigo,


Thank you for your detailed answer! All clear.

I finally managed to do it but without using the snap functionality, cause I needed to scroll up and down. The solution was based on another example found on the forum by @ZachSaucier (the codepen :

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

, and the thread:


Here is the (a) solution :


let panels = gsap.utils.toArray('.block-scroll'),

function goToSection(i) {
  scrollTween = gsap.to(window, {
    scrollTo: {y: i * innerHeight, autoKill: false},
    duration: 1,
	ease: Power3. easeOut,
    onComplete: () => scrollTween = null,
    overwrite: true

panels.forEach((panel, i) => {
		//markers: true,
    trigger: panel,
    start: 'top 75%',
    end: 'top 25%',
    onEnter: self => {
      self.isActive && !scrollTween && goToSection(i+1);
    onEnterBack: self => {
      self.isActive && !scrollTween && goToSection(i);


Anyway, thanks for your quick answer.


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.