Janky parallax text with GSAP
Asked Answered
A

1

6

I've tried to make a text with parallax and failed. Code seems innocuous and doesn't seem to be doing anything wrong, yet the scroll look&feel is quite wrong.

Markup is like this:

<!-- content above -->
<section class="section-parallax">
  <div class="container text-center">
    <div class="flex-row-columns">
      <div class="flex-row">
        <h2 class="heading flex-8">
          <span class="heading-sub">Some Header</span>
          <span class="heading-bottom">getting also long<sup>
        </h2>
      </div>
    </div>
  </div>
</section>
<!-- content below -->

Styles like this:

.container {
  box-sizing: border-box;
  margin-left: auto;
  margin-right: auto;
  padding-left: 15px;
  padding-right: 15px;
  width: 1400px;
}

.text-center {
  text-align: center;
}

.section-parallax {
  background: black;
  overflow: hidden;

  &,
  & .container,
  & .flex-row {
    min-height: 545px;
  }

  & .container {
    transform: translate3d(0, -100%, 0);
  }
}

.flex-row-columns {
  display: flex;
  flex-direction: column;
  margin-top: 0;
  margin-bottom: 0;
  margin-left: 0;
  margin-right: 0;
}

.flex-row {
  align-items: center;
  display: flex;
  justify-content: center;
  margin-left: -15px;
  margin-right: -15px;
}

.flex-8 {
  flex-basis: 66.66666666666667%;
  padding-left: 15px;
  padding-right: 15px;
}

.heading {
  color: white;
  font-size: 54px;
  letter-spacing: .66px;
  line-height: 1.273em;
}

.heading-sub {
  display: block;
  margin-bottom: 20px;
}

And finally the JS I've used is like this:

class ParallaxSection {
  constructor() {
    this.el = document.querySelector('.section-parallax');
    this.els = {
      container: this.el.querySelector('.container')
    };
    this.calcBounds();

    window.addEventListener('scroll', this.onScroll.bind(this));
    window.addEventListener('resize', () => {
      this.calcBounds();
      this.onScroll();
    });
  }

  calcBounds() {
    if (this.tween) {
      this.tween.kill();
      this.els.container.removeAttribute('style');
    }

    const rect = this.el.getBoundingClientRect();
    const scrollY = ParallaxSection.getScroll();

    this.start = (rect.top + scrollY) - (window.innerHeight * 0.75);
    this.end = this.start + this.el.offsetHeight + window.innerHeight;
    this.tween = TweenLite.fromTo(this.els.container, 1, {
      css: {
        force3D: true,
        y: -this.el.offsetHeight
      }
    }, {
      paused: true,
      css: {
        force3D: true,
        y: this.end - this.start - this.el.offsetHeight
      },
      ease: Linear.easeNone
    });
  }

  onScroll() {
    const scroll = ParallaxSection.getScroll();

    if (scroll >= this.start && scroll <= this.end) {
      const diff = this.end - this.start;
      const offset = scroll - this.start;
      const perc = offset / diff;
      this.tween.progress(perc);
    }
  }

  static getScroll() {
    return window.pageYOffset || document.documentElement.scrollTop;
  }
}

const p = new ParallaxSection();

Now, the odd thing is that while trying to discover the issue I put this into a Pen so I could try to see where it failed and in the pen seemed alright. That led me to remove all the elements on my page and replicate the pen exactly, turns out that, for some unknown reason the effect is perfect on codepen and fails out of it.

I've downloaded the whole HTML that codepen generates and it suffers the same experience.

enter image description here

Pen is here to be seen.

What's wrong with it?

Amygdalin answered 24/3, 2017 at 15:7 Comment(7)
Do you really need GSAP for this? You can replicate this effect by having a fixed container.Peroxy
You don't need to use the CSSPlugin for this, you can animate the 'y' property directly. I wouldn't have thought that would be enough to make it 'janky' though. If things are different between codepen/local it may be that one of your container <div>'s does not have transform: translateZ(0) on it and codepen`s does? The code looks reasonable to me.Woermer
Is it bad all the time for you, or just when you get to the parallax section?Woermer
Effect just seems wrong on the parallax section. FPS on scrolling seems 60 all the time anyway. Codepen seems now wrong too after this: twitter.com/CodePen/status/845351286816096256 using translate3d so it could be smoother.Amygdalin
@AntonioLaguna when you say you've downloaded, do you mean that you used the export feature? After exporting I was still unable to replicate the issues, perhaps your computer is being slow when accessing the file directly? Have you tried running it on a local server to see if it still occurs?Walton
Some of the html is invalid <span class="heading-bottom">getting also long<sup>. Doesn't look like you're closing the spanShoop
I'd try to make the white text fixed (absolute position) and only scroll the black part behind it, plus some JS code to show and hide the white letters at the correct moment. That'll remove your jitter. example: codepen.io/anon/pen/evxrXY (not incluing the hiding logic)Strobile
C
0

I think the problems comes from trying to execute the logic on every scrolled pixel. Maybe you can fix that by using:

Campagna answered 20/4, 2017 at 11:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.