Jump to content
GreenSock

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

ScrollTrigger - Horizontal Scrolling

Recommended Posts

Hello,

 

As per the Horizontal scrolling demo ->

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

 you can see the container is a fixed width of 600% and the child sections are 100% so this works fine with 6 children

 

I'm trying to understand how to create a horizontal scrolling container with child elements, who's width's are dynamic. 

You can see in my codepen example -> https://codepen.io/KyleAtSlik/pen/VwewmPz the measurements are off and the red square is missing.

I'm just wondering if anyone has any ideas as to why this is?

See the Pen VwewmPz by KyleAtSlik (@KyleAtSlik) on CodePen

  • Like 1
Link to comment
Share on other sites

The problem is that your #container element is NOT the full width of all its contents. It is only as wide as the screen. So everything is working the way it's supposed to from GSAP's perspective, but you've got it only moving xPercent: -100 which means it moves to the left by the width of the screen (not nearly enough). 

 

So all you'd need to do is correct the distance you want it to travel so that it's the entire width of all your elements MINUS the width of the screen (otherwise it'll go all the way off the screen). So your tween could be: 

 

gsap.to(container, {
  x: () => -(container.scrollWidth - document.documentElement.clientWidth) + "px",
  ease: "none",
  scrollTrigger: {
    trigger: container,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 1,
    end: () => "+=" + container.offsetWidth
  }
})

Here's a fork:

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

 

Is that what you were looking for? 

  • Like 6
Link to comment
Share on other sites

Thank you!

 

This is awesome, greatly appreciated


 

  • Like 2
Link to comment
Share on other sites

No problem! Enjoy ScrollTrigger and your new scrolling superpowers :)

 

  • Like 2
Link to comment
Share on other sites

  • 1 month later...

Hi, thank you for sharing! May I as you two questions?
With your code updated, is there a way to add a pin inside one of the slide? 

(For example, I'm trying to pin a nav menu from secondo slide until end! Is this theoretically possible?)

 

And, I'm trying to use this example (

See the Pen bGVjLwG?editors=1111 by GreenSock (@GreenSock) on CodePen

) to implement your horizontal scrolling with a nav menu. I manage to scroll to the right position using gsap.to against horizontal scroll container (not against window object), but I can't keep vertical scrollbar in sync with my elements. I'm sure this is conceptually wrong, but I can't imagine a different way :D

 

gsap.registerPlugin(ScrollTrigger)
gsap.registerPlugin(ScrollToPlugin);

// your horizontal scrolling
gsap.to(container, {
  x: () => -(container.scrollWidth - document.documentElement.clientWidth) + "px",
  ease: "none",
  scrollTrigger: {
    trigger: container,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 1,
    end: () => "+=" + container.offsetWidth
  }
})

// edited nav code from other example
gsap.utils.toArray("nav a").forEach(function(a) {
  a.addEventListener("click", function(e) {
    e.preventDefault();
    const el = document.querySelector(e.target.getAttribute('href'))

    console.log(el.getBoundingClientRect())

    console.log(container)

    gsap.to(container, {
      duration: 1,
      x: -(el.getBoundingClientRect().x)
      /*scrollTo: {y: el.getBoundingClientRect()}*/
    });
  });
});

 

 

Link to comment
Share on other sites

On 7/12/2020 at 6:20 AM, MarcoMessa said:

is there a way to add a pin inside one of the slide? 

(For example, I'm trying to pin a nav menu from secondo slide until end! Is this theoretically possible?)

I would consider putting the element outside of the slide 2 container, use position: absolute to position it where you need to, then pin it when it's reached. 

 

Alternatively try using position: sticky but whether or not that can work likely depends on your markup.

Link to comment
Share on other sites

  • 2 months later...

Hello

 

I'm using the horizontal scroll example provided by Jack inside a pinned section which works a treat but I also have elements above and below that have fade/slide animations triggered as they scroll into view. The ones above the pinned section work fine but the ones below trigger early because the height of the pinned section doesn't take into account the width of the elements scrolling horizontally inside it:

 

<div class="pin-spacer" style="flex-shrink: 1; display: flex; margin: 0px; right: 0px; bottom: 0px; top: 0px; left: 0px; position: relative; overflow: visible; box-sizing: border-box; width: 1632px; height: 2596px; padding: 0px 0px 1632px;">
  <section id="fix-section" style="transform: translate3d(-270px, 0px, 0px); left: 0px; top: -0.40625px; margin: 0px; width: 1632px; height: 964px; padding: 0px; box-sizing: border-box; max-width: 1632px; max-height: 964px; position: fixed;">
    ... ELEMENTS HERE ...
    </section>
</div>

The pin-spacer has the calculated full height of all the elements inside it (2596px) but the fixed-section only has the single contained element height (964px) so the animated items below fire once 964px has been reached rather than waiting for 2596px.

 

I've tried making a pen of this but can't replicate so hope the above generated code is of use.

 

Can I force the elements below to wait until the pinned section has ended?

 

Thanks in advance.

Link to comment
Share on other sites

Hey @cottoncreative. Most likely it has to do with the order in which your ScrollTriggers are created. They should be created in the order that they are displayed on the page in order to get their calculations correct. Alternatively you could use the refreshPriority property of ScrollTrigger to order the ScrollTriggers. It's hard to say for sure without a minimal demo though.

  • Like 2
Link to comment
Share on other sites

FYI I just added another section to the common ScrollTrigger mistakes article that talks about the order of ScrollTriggers along with demos:

 

  • Like 3
Link to comment
Share on other sites

Thanks a million @ZachSaucier, that's exactly what it was.

I've popped the slide/fade anims after the pin trigger and all works well above and below it now.

Link to comment
Share on other sites

On 6/2/2020 at 11:59 PM, GreenSock said:

The problem is that your #container element is NOT the full width of all its contents. It is only as wide as the screen. So everything is working the way it's supposed to from GSAP's perspective, but you've got it only moving xPercent: -100 which means it moves to the left by the width of the screen (not nearly enough). 

 

So all you'd need to do is correct the distance you want it to travel so that it's the entire width of all your elements MINUS the width of the screen (otherwise it'll go all the way off the screen). So your tween could be: 

 


gsap.to(container, {
  x: () => -(container.scrollWidth - document.documentElement.clientWidth) + "px",
  ease: "none",
  scrollTrigger: {
    trigger: container,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 1,
    end: () => "+=" + container.offsetWidth
  }
})

Here's a fork:

 

 

 

Is that what you were looking for? 


 

I used this example for a website and I't works great but I have a problem, my client want this to work with a trackpad, so like if you're in a macbook you can swipe to the sides instead of up/down, it's there a way to do this?

 

Here is my website https://dev-shapetx.pantheonsite.io/therapeutics-platform/

Link to comment
Share on other sites

12 hours ago, kevchcm said:

my client want this to work with a trackpad, so like if you're in a macbook you can swipe to the sides instead of up/down, it's there a way to do this?

If you need to support both (mouse and side scrolling) it'd probably be best to use a library like HammerJS to detect when someone has swiped sideways and then move the page accordingly. But yes, it's definitely possible.

Link to comment
Share on other sites

On 10/9/2020 at 6:21 AM, ZachSaucier said:

If you need to support both (mouse and side scrolling) it'd probably be best to use a library like HammerJS to detect when someone has swiped sideways and then move the page accordingly. But yes, it's definitely possible.

Hey thank you for the suggestion, unfortunately that plugin didn't work, but I'll try to make it work with javascript. 

 

 

I have another question regarding my horizontal scroll site https://dev-shapetx.pantheonsite.io/therapeutics-platform/
Is there a way to know when a section is visible on the viewport. I have to add some animations to the text when a section shows up

Link to comment
Share on other sites

1 minute ago, kevchcm said:

Is there a way to know when a section is visible on the viewport. I have to add some animations to the text when a section shows up

Sure, you just need to calculate when that is. More about that in this thread:

 

Link to comment
Share on other sites

  • 2 weeks later...

Is there any option in order to scroll to the left or to the right and make changes with ScrollTriggers? I have been trying to do it, but gsap only detects vertical scrolling, not horizontal scrolling. 

 

I'm trying to do something like that https://robin-noguier.com The effect that I want it is only seen in mobile responsive.

 

Thanks.

Link to comment
Share on other sites

Hey Marc and welcome to the GreenSock forums.

 

1 hour ago, MarcOlmos said:

Is there any option in order to scroll to the left or to the right and make changes with ScrollTriggers? I have been trying to do it, but gsap only detects vertical scrolling, not horizontal scrolling. 

That's exactly what the horizontal property of ScrollTrigger is for :) Set it to true when the scroller is horizontal and it will work. More info in the docs.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

Hello, new member here. Been using your library for a long time =)  First time trying out a horizontal site, finally got a request to do one.  So using ScrollTrigger for this functionality.  Basically trying to replicate the examples in this post. 

 

However, its not quite working right.   I have 4 divs inside the container.  These divs are set to 100% width ( may need to use pixels, let me know )

 

When I run, it works... I see the first "section" div, it scrolls but the other divs are hidden.  When I inspect, the container has overflow set to hidden, which explains why the rest of the divs are not visible.  When I disable overflow, all the sections show up and works fine.

 

I curious on what I'm doing wrong here, when I inspect the code in this post, the container does not have overflow set at all, but on mine it does.

 

Below is a condensed version on my end, the parent-container div is just the outer element.  I added it so its close to how I have it setup.  

 

<style> 
.parent-container {
  width: 100%;
}
.container {
  display:flex;
  flex-wrap:wrap;
  flex-direction:column;
  height:100vh;
}
.section {
  position: relative;
  display: flex;  
  width: 100%;	// Use Pixels instead?
  height: 100%;
  padding: 0 40px 0 80px;
  margin: 40px 0;
}
</style>

<div class="parent-container">
  <div class="container">
    <div class="section"></div>
    <div class="section"></div>
    <div class="section"></div>
    <div class="section"></div>    
  </div>
</div>

 

this.scrollContent = document.getElementsByClassName("container")[0];

this.gsap.to(this.scrollContent, {
  x: () => -(this.scrollContent.scrollWidth - document.documentElement.clientWidth) + "px",
  ease: "none",
  scrollTrigger: {
    trigger: this.scrollContent,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 1,
    end: () => "+=" + this.scrollContent.offsetWidth
  }
})

Any help would be appreciated.

 

Looked at the line where it actually sets overflow: hidden --- 

ScrollTrigger.js Line 896

pin.firstChild && !_maxScroll(pin, direction) && (pin.style.overflow = "hidden"); // protects from collapsing margins!

 

 

 

Thanks you!

Link to comment
Share on other sites

Hey @fania and welcome to the GreenSock forums.

 

Can you please create a minimal demo of your issue using CodePen or something? It's probably also best to start a new thread about your issue.

Link to comment
Share on other sites

Hey thanks for the response, yes of course, will do soon.  Thank you!

Link to comment
Share on other sites

  • 2 weeks later...

 

Hey @justanothergoonie

 

Since you are not scrolling by using the browser's native horizontal scrolling behaviour here, but only 'faking' a horizontal scroll when scrolling vertically, your ScrollTrigger with horizontal set to true will not work as you probably expect.

 

If you want to add animations to the individual sections/elements e.g. when they enter the viewport, you would have to do the calculations for when to trigger what, yourself.

 

These threads here contain examples on how to do that. You could probably apply a similar concept to your example.

The second one also contains a detailed explanation on what to consider in a scenario like yours

 

 

 

 

Also there is this just recently added demo on the ScrollTrigger demo-page that might help:

 

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

 

 

 

And here is an example-setup using your pen to get you started in the right direction (toggling the .active class when the left of the section hits the center of the viewport.

 

See the Pen 04e0bded73630f24573f58a768ffafa8 by akapowl (@akapowl) on CodePen

 

 

 

Hope this helps.

 

Cheers,

Paul

 

  • Like 3
Link to comment
Share on other sites

  • 6 months later...
On 6/3/2020 at 11:29 AM, GreenSock said:

The problem is that your #container element is NOT the full width of all its contents. It is only as wide as the screen. So everything is working the way it's supposed to from GSAP's perspective, but you've got it only moving xPercent: -100 which means it moves to the left by the width of the screen (not nearly enough). 

 

So all you'd need to do is correct the distance you want it to travel so that it's the entire width of all your elements MINUS the width of the screen (otherwise it'll go all the way off the screen). So your tween could be: 

 


gsap.to(container, {
  x: () => -(container.scrollWidth - document.documentElement.clientWidth) + "px",
  ease: "none",
  scrollTrigger: {
    trigger: container,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 1,
    end: () => "+=" + container.offsetWidth
  }
})

Here's a fork:

 

hi ,

I tried to add animations for inside panel elements using scrolltrigger.. but it doesnt work.. pls help me

 

 

Link to comment
Share on other sites

On 6/3/2020 at 11:29 AM, GreenSock said:

The problem is that your #container element is NOT the full width of all its contents. It is only as wide as the screen. So everything is working the way it's supposed to from GSAP's perspective, but you've got it only moving xPercent: -100 which means it moves to the left by the width of the screen (not nearly enough). 

 

So all you'd need to do is correct the distance you want it to travel so that it's the entire width of all your elements MINUS the width of the screen (otherwise it'll go all the way off the screen). So your tween could be: 

 






gsap.to(container, {
  x: () => -(container.scrollWidth - document.documentElement.clientWidth) + "px",
  ease: "none",
  scrollTrigger: {
    trigger: container,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 1,
    end: () => "+=" + container.offsetWidth
  }
})

Here's a fork:

 

hi ,

I tried to add animations for inside panel elements using scrolltrigger.. but it doesnt work.. pls help me

See the Pen BaRPGqZ?editors=1100 by pradeepppi (@pradeepppi) on CodePen

On 6/3/2020 at 11:29 AM, GreenSock said:

 

 

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