Jump to content
Search Community

Scrolltrigger buggy when site breaks to mobile

MarkD617 test
Moderator Tag

Recommended Posts

I have a Nuxt / Vue App and when the app breaks to mobile (991px) I have a strange bug happening with scrollTrigger / Pin. What is happening is the timeline I am pinning is showing at the top of the page as if scrollTrigger is not initialized?  As I scroll down the page the timeline remains fixed and then readjusts back to its position in the DOM but it is not working correctly even at that point. If I refresh the page it works fine, even in mobile. I tried calling ScrollTrigger.refresh() on the mounted hook but with no luck. The only other element that is using ScrollTrigger is my site header so I was thinking that could possibly be causing a clash.

 

Any thoughts?

<template>
  <div id="pinVerticalScroll">
    <section
      class="grand-carousel-band section-band grand-carousel--history bg-prism bg-prism--a-left-green-plum"
    >
      <div class="container-outer">
        <section class="grand-carousel-body grand-carousel-body-history">
          <div class="container-outer l-section-band">
            <section
              class="grand-carousel-body grand-carousel-body-history pb-5 pb-md-0"
            >
              <header class="grand-carousel-body-header">
                <div class="container container--nested-lg">
                  <div class="row">
                    <div class="col-lg-7">
                      <h2 class="title-3 grand-carousel-body-title">
                        title</em>
                      </h2>
                      <p>
                       copy
                      </p>
                    </div>
                  </div>
                </div>
              </header>

              <div
                class="container container__timeline mb-5 pb-5 mb-md-0 pb-md-0"
                
              >
                <div class="timeline-nav">
                  <ul class="timeline-nav__list">
                    <li class="is-active timeline-nav__list-item">One</li>
                    <li class="timeline-nav__list-item">Two</li>
                    <li class="timeline-nav__list-item">Three</li>    
                  </ul>
                </div>

                <div class="timeline-slides">
                  <div class="slide">
                    <div class="slide--inner">
                      <div class="timeline-title">
                        <h3>Slide One</h3>
                      </div>
                    </div>
                  </div>

                    <div class="slide">
                    <div class="slide--inner">
                      <div class="timeline-title">
                        <h3>Slide Two</h3>
                      </div>
                    </div>
                  </div>


                    <div class="slide">
                    <div class="slide--inner">
                      <div class="timeline-title">
                        <h3>Slide Three</h3>
                      </div>
                    </div>
                  </div>

              
                  </div>
                </div>
              </div>
            </section>
          </div>
        </section>
      </div>
    </section>
  </div>
</template>
<script>
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger.js';
gsap.registerPlugin(ScrollTrigger);
export default {
  name: 'ContentAboutUsHistory',
  components: {},
  data() {
    return {};
  },
  methods: {},
  mounted() {
    const gsap = this.$gsap;
    const sections = gsap.utils.toArray('.slide');
    const numSections = sections.length - 1;
    const snapValue = 1 / numSections;
    let oldIndex = 0;
    const navList = document.querySelectorAll('.timeline-nav__list-item');

    if (sections.length > 0) {
          gsap.to(sections, {
            yPercent: -100 * numSections,
            ease: 'none',
            scrollTrigger: {
              id: 'aboutTimeline',
              pin: '#pinVerticalScroll',
              scrub: true,
              snap: snapValue,
              end: '+=4000',
              onUpdate: (self) => {
                const currentIndex = Math.round(self.progress / snapValue);
                if (currentIndex !== oldIndex) {
                  navList[oldIndex].classList.remove('is-active');
                  navList[currentIndex].classList.add('is-active');
                  oldIndex = currentIndex;
                }
              },
            },
          });
        }
      });
    }
  },
  beforeDestroy() {
    ScrollTrigger.getById('aboutTimeline').kill();
  },
};
</script>

 

 

 

 

 

Link to comment
Share on other sites

It's super tough to troubleshoot blind but based on the fact that it works fine if you refresh, my guess is that your framework is still messing with the DOM after you call ScrollTrigger.refresh(). Have you tried putting that in a single requestAnimationFrame() or a setTimeout() that just waits a short time before calling ScrollTrigger.refresh()? I'm not saying that's a long-term solution, but it would help identify if it's an issue with your framework not settling things properly first. 

 

It's always best to provide a minimal demo, like in CodeSandbox or CodePen - that gives you the best chance of getting a solid answer. 

 

Happy tweening/scrolling!

Link to comment
Share on other sites

Hi Jack, So I added a setTimeout() to the vue mounted lifecycle hook and it worked however The timeout duration had to be at least 1000 for it to refresh the instance. The strange behavior is still flashing quickly and then it refreshes into place. Thank you for the direction, good to know it is a framework issue and not gsap issue.

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