artemijeka
3/1/2021 - 6:41 PM

Фиксация блоков при прокрутке (jQuery) | Block fixing when scrolling (jQuery)

Фиксация блоков при прокрутке | Block fixing when scrolling

/**
 * @version 2.0
 * @author  Artem Kuznecov
 * @email   work.artem.kuznecov.samara@yandex.ru
 * @website web.master-artem.ru
 * @link    https://snippets.cacher.io/snippet/79e169f9ca705c345531
 * @param   {String}  obj.blockSelector
 * @param   {Boolean} obj.fixAtTop
 * @param   {String}  obj.fixUnderBlock
 * @param   {String}  obj.fixOverBlock
 * @param   {Number}  obj.blockMarginBottomPx
 */
 function Fixer(obj) {
  var self = this;
  this.$block = $(obj.blockSelector);
  this.windowPxOfTop = null;
  this.blockOffsetTopDynamic = null;
  this.blockOffsetTopFixed = null;
  // this.height = null;
  this.fixed = false;
  this.pxOfTop = null;
  this.cssTop = self.$block.css('top');
  this.cssTopNumber = parseFloat(self.$block.css('top'));
  this.marginBottomPx = obj.blockMarginBottomPx || 0;
 
  this.loopLoadScrollResizeWindow = function () {
    $(window).on('load scroll resize', function () {
      this.windowPxOfTop = $(window).scrollTop();
      // this.height = self.$block.height();
      this.blockOffsetTopDynamic = self.$block.offset().top;
 
      if (obj.fixAtTop) {
        if (!this.fixed && (this.windowPxOfTop >= this.blockOffsetTopDynamic)) {
          this.blockOffsetTopFixed = this.blockOffsetTopDynamic;
          self.$block.css({
            'position': 'fixed',
            'top': '0'
          });
          this.fixed = true;
        } else if (this.fixed && (this.windowPxOfTop <= this.blockOffsetTopFixed)) {
          self.$block.css({
            'position': '',
            'top': ''
          });
          this.fixed = false;
        }
      }
 
      if (obj.fixUnderBlock) {
        if (this.windowPxOfTop < $(obj.fixUnderBlock).height()) {
          self.$block.css({
            'top': 'calc(' + self.cssTop + ' - ' + this.windowPxOfTop + 'px)'
          });
        } else {
          self.$block.css({
            'top': 'calc(' + $(obj.fixUnderBlock).height() + 'px)'
          });
        }
      }
 
      if (obj.fixOverBlock) {
        var underBlockOfViewport = document.querySelector(obj.fixOverBlock).getBoundingClientRect();
        var blockHeight = self.$block.height();
        var calcTopOfViewport = ( underBlockOfViewport.top - blockHeight - self.marginBottomPx);
 
        if ( underBlockOfViewport.top < (blockHeight + self.cssTopNumber + self.marginBottomPx) ) {
          self.$block.css({
            'top': calcTopOfViewport + 'px',
          });
        } else {
          self.$block.css({
            'top': self.cssTop,
          });
        }
 
      }
    });
  }();

}

Фиксация блоков при прокрутке | Block fixing when scrolling

jquery.fixer.js

Зависимости | Dependencies:

jquery-3.6.0.min.js

Фиксация блока при прокрутке по верху окна | Fixing a block when scrolling along the top of the window:

var headerNav = new Fixer({
  blockSelector: '.header__nav',
  fixAtTop: true,
});

Фиксация блока по низу предыдущего блока, при прокрутке | Fixing a block when scrolling along the bottom of the previous block:

var headerMobileMenu = new Fixer({
  blockSelector: '.header__mobile-menu',
  fixUnderBlock: '.header__nav',
});

Фиксация блока по верху нижелещащего блока, при прокрутке | Fixing a block to the top of the underlying block when scrolling:

var sidebarMenu = new Fixer({
  blockSelector: '.sidebar-menu',
  fixOverBlock: '.form-bottom',
  blockMarginBottomPx: 40,
});

#jquery_module_fixer #frontend_module_fixer #jquery_module_fixer_scrollig #frontend_module_fixer_scrollig #jquery_module_fixer_scroll #frontend_module_fixer_scroll #jquery_module_scroll_fixer #frontend_module_scroll_fixer #jquery_module_scrolling_fixer #frontend_module_scrolling_fixer