Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Damian Balas

ScrollTrigger - Horizontal Scrolling

Recommended Posts

Hi, 
I need some help with horizontal scrolling.
I can't provide you with a CodePen example.

My env.:
Next.js
GSAP (newest version at the moment)

My <body> element contains a <Layout> element which is set like this:

 

.layout {

  display: flex;

  flex-direction: row;

  width: 100vw;

  height: 100vh;

  overflow-y: auto;



  main {

    display: flex;

    flex-direction: column;

    flex-grow: 1;

    overflow-y: auto;

    overflow-x: hidden;

  }

}

Inside <main> I'm trying to implement something simmilar to the codepen 

My version looks like this:

 

export const HorizontalScrollTiles: React.FC = () => {

  useEffect(() => {
    const container = document.querySelector('.abc');
    const scroller = document.getElementById('main');

    gsap.to(container, {
      x: () =>
        `${-(container.scrollWidth - document.documentElement.clientWidth)}px`,
      ease: 'none',
      scrollTrigger: {
        scroller,
        trigger: container,
        invalidateOnRefresh: true,
        pin: true,
        scrub: 1,
        end: () => `+=${container.offsetWidth}`,
      },
    });
  }, []);

  return (
    <div
      className="abc"
      style={{
        minHeight: '100vh',
        display: 'flex',
        flexWrap: 'nowrap',
        width: '600%',
      }}>
      <Tile
        className="horizontal-scroll-tile"
        style={{ width: '100%', backgroundColor: '#ff22ff' }}
      />
      <Tile
        className="horizontal-scroll-tile"
        style={{ width: '100%', backgroundColor: '#ffff2f' }}
      />
      <Tile
        className="horizontal-scroll-tile"
        style={{ width: '100%', backgroundColor: '#f29fff' }}
      />
      <Tile
        className="horizontal-scroll-tile"
        style={{ width: '100%', backgroundColor: '#ff8029' }}
      />
      <Tile
        className="horizontal-scroll-tile"
        style={{ width: '100%', backgroundColor: '#ffff99' }}
      />
      <Tile
        className="horizontal-scroll-tile"
        style={{ width: '100%', backgroundColor: '#11ffff' }}
      />
    </div>
  );
};

Tile Element is just a <div> containing another <div> with a <h2>

I'm going to explain the problem now:

First of all, the code does something only if I set markers: true it's not perfect, but at least I can scroll almost to the end of the last <Tile>
Without markers set to true, I can't scroll at all.

Do you have any ideas/suggestions how to implement this functionality? 
It's really important.

With markers set to true:
image.thumb.png.437d868a2ad1bde11631f918cc10c7a1.png
 

and without:
image.thumb.png.ff1ef85c7efeb9f330fff49e2547f1af.png

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

Link to comment
Share on other sites

Maybe it helps to find a solution:
I found out that scroller start and scroller end are in the same spot and it's following while scrolling:
image.png.707f3ac6c773c3dc4bd4822a4254b04d.png

Link to comment
Share on other sites

@OSUblake yes, I had to change the Layout. Flex was messing with everything.

My horizontal scroll is a bit laggy... Are there any options to make the animation crisp? :) 


 

const initializeHorizontalScroll = (): GsapKill => {
  const container = document.getElementById('horizontal-scroll-wrapper');
  const navigation = document.getElementById('main-navigation');

  if (!container) {
    throw new Error('Container cannot be null!');
  }

  const navigationWidth = navigation
    ? navigation.getBoundingClientRect().width
    : 0;
  const xValue =
    container.scrollWidth -
    document.documentElement.clientWidth +
    navigationWidth;

  if (xValue <= 0) {
    throw new Error(
      `Cannot initialize horizontal scroll, because there is nothing to scroll. xValue: ${xValue}`,
    );
  }

  const animation = gsap.to(container, {
    x: () => `${-xValue}px`,
    ease: 'none',
    scrollTrigger: {
      trigger: container,
      invalidateOnRefresh: true,
      start: 'top top',
      pin: true,
      scrub: 0.5,
      end: () => container.offsetWidth,
    },
  });
  return animation.kill;
};

 

Link to comment
Share on other sites

Hard to say without seeing it. 

 

You can try adding will-change in your CSS to whatever you're animating.

.foo {
  will-change: transform;
}

 

  • Thanks 1
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.
×