artemijeka
7/6/2021 - 1:18 PM

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

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

/**
 * @version 3.4 - 17.10.2022
 * @author  Artem Kuznecov
 * @email   artem.kuznecov.samara@yandex.ru
 * @website https://web.master-artem.ru
 * @source  https://snippets.cacher.io/snippet/79e169f9ca705c345531
 * @source  https://gist.github.com/artemijeka/130fd58f6859999faafcea60de686262
 * @param {String}  obj.target        | Блок который фиксируем
 * @param {Boolean} obj.fixAtTop      | Зафиксировать везде начиная с верха сайта
 * @param {Boolean} obj.fixAfter      | Зафиксировать после ухода этого блока за верх экрана
 * @param {String}  obj.fixUnderBlock |
 * @param {String}  obj.fixOverBlock  |
 * @param {Number}  obj.marginBottom  |
 */
function Fixer(obj) {
  var self = this;
  this.target = document.querySelector(obj.target);
  this.fixAfter = document.querySelector(obj.fixAfter);
  this.windowOfTop = null;
  this.targetOfTop = null;
  this.targetOffsetTopFixed = null;
  // this.height = null;
  this.fixed = false;
  this.pxOfTop = null;
  this.targetAbove = document.querySelector(obj.fixUnderBlock);
  this.cssTop = window.getComputedStyle(self.target).getPropertyValue("top");
  this.cssTopNumber = parseFloat(this.cssTop);
  this.marginBottomPx = obj.marginBottom || 0;

  this.loopLoadScrollResizeWindow = (function () {
    ["load", "scroll", "resize"].forEach(function (event) {
      window.addEventListener(event, function () {
        self.windowOfTop = window.scrollY;
        // this.height = self.target.height;
        self.targetOfTop = self.target.offsetTop;

        if (obj.fixAfter) {
          if (self.fixAfter.getBoundingClientRect().top <= 0) {
            self.target.classList.add("--fixed");
          } else {
            self.target.classList.remove("--fixed");
          }
        }

        if (obj.fixAtTop) {
          if (!self.fixed && self.windowOfTop > self.targetOfTop) {
            self.targetOffsetTopFixed = self.targetOfTop;
            self.target.style.position = "fixed";
            self.target.style.top = "0";
            // self.target.classList.add('--fixed');
            self.fixed = true;
          } else if (
            self.fixed &&
            self.windowOfTop < self.targetOffsetTopFixed
          ) {
            self.target.style.position = "";
            self.target.style.top = "";
            // self.target.classList.remove('--fixed');
            self.fixed = false;
          }
        }

        if (obj.fixUnderBlock) {
          if (
            self.windowOfTop < self.targetAbove.getBoundingClientRect().height
          ) {
            self.target.classList.add("--fixed");
            self.target.style.top =
              "calc(" + self.cssTop + " - " + self.windowOfTop + "px)";
          } else {
            // self.target.classList.remove('--fixed');
            self.target.style.top =
              "calc(" + self.targetAbove.getBoundingClientRect().height + "px)";
          }
        }

        if (obj.fixOverBlock) {
          var blockAboveOfViewport = document
            .querySelector(obj.fixOverBlock)
            .getBoundingClientRect();
          var targetHeight = self.target.getBoundingClientRect().height;
          var calcTopOfViewport =
            blockAboveOfViewport.top - targetHeight - self.marginBottomPx;

          if (
            blockAboveOfViewport.top <
            targetHeight + self.cssTopNumber + self.marginBottomPx
          ) {
            self.target.style.top = calcTopOfViewport + "px";
          } else {
            self.target.style.top = self.cssTop;
          }
        }
      });
    });
  })();
}
.--fixed {
	position: fixed;
}

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

fixer.js

Ссылка на видео представление 1
Ссылка на видео представление 2

Usage:

Фиксация блока при прокрутке по верху окна | 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,
});

#module_fixer #frontend_module_fixer #module_fixer_scrollig #frontend_module_fixer_scrollig #module_fixer_scroll #frontend_module_fixer_scroll #module_scroll_fixer #frontend_module_scroll_fixer #module_scrolling_fixer #frontend_module_scrolling_fixer