javascriptjqueryscrollmagic

ScrollMagic responsive duration / endpoint for a sticky nav?


I'm using Scroll Magic for a sticky side nav. I would like the side nav to STOP right before the next section but as of now the duration endpoint is showing about 200px below where I would want. How do you set a custom endpoint regardless of the height of the content? I tried adding a negative value to the height of the duration point but then on certain pages where the height was smaller it did not work and overflowed into the next section. My ideal outcome is the sticky nav ALWAYS stops about 15px before the bottom of the .center-tab-content section.

  if ($('.container--tab-navigation').length) {
      var pinPageNavController = new ScrollMagic.Controller(),
        pinPageScene = new ScrollMagic.Scene({
          triggerElement: '.l-side-nav',
          triggerHook: 'onLeave',
          duration: getHeightDuration,
        })
          .addIndicators({ name: '2 (duration: 0)' }) // add indicators (requires plugin)
          .addTo(pinPageNavController);

      pinPageScene.setPin('.l-side-nav', { pushFollowers: false });

      function getHeightDuration() {
        var heightDuration = Number($('.center-tab-content').height());
        return heightDuration;
      }
    }

Solution

  • Difficult to tell without the full code but the duration of the scene should be the height upto that point.

    Example: https://codepen.io/alexpetergill/pen/GRNBZKB

    In the example above, we want the sticky nav to stop at the bottom of section 2 so as its the second section we can just get the height of section and multiply this by 2 (assuming your sections are the same height!)

    var scene = new ScrollMagic.Scene({
      triggerElement: '#nav',
      duration: $('section').outerHeight() * 2
    })
      .setPin('#nav', {pushFollowers: false})
      .addTo(controller);
    

    Also worth noting your are using the height() method for your calculation which at a guess is properly more the issue as this will not calculate how you think if the section has padding for example. Recommend you use outerHeight() method to ensure its the full height of that element.

    Updated answer

    As discussed, if your sections are variable in height then I would suggest calculating the height of all previous sections and target section. (example also updated!)

    var scene = new ScrollMagic.Scene({
      triggerElement: '#nav',
      duration: getDuration()
    })
      .setPin('#nav', {pushFollowers: false})
      .addTo(controller);
    
    function getDuration() {
      var $section2 = $('.section-2')
      var $prevSections = $section2.prevAll('section')
      var outerHeight = 0;
      $prevSections.each(function() {
        outerHeight += $(this).outerHeight();
      });
      var duration = $section2.outerHeight() + outerHeight;
      return duration;
    }