Skip to content

Instantly share code, notes, and snippets.

@JamesBondsky
Forked from artemsites/Fixer.js
Created April 11, 2023 23:26
Show Gist options
  • Save JamesBondsky/5573c1cabc996d5ddfcb942a13292444 to your computer and use it in GitHub Desktop.
Save JamesBondsky/5573c1cabc996d5ddfcb942a13292444 to your computer and use it in GitHub Desktop.
Фиксация блоков при прокрутке | Block fixing when scrolling

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

fixer.js

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

При фиксации наверху target просто задаётся класс --fixed и его надо стилизовать под себя.

Usage:

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

var headerNav = new Fixer({
  target: node,
  fixAtTop: true,
});

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

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

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

var sidebarMenu = new Fixer({
  target: '.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

/**
* @version 3.5 - 21.02.2023
* @author Artem Kuznecov
* @email artem@web-ascent.ru
* @website https://web-ascent.ru
* @source https://snippets.cacher.io/snippet/79e169f9ca705c345531
* @source https://gist.github.com/artemijeka/130fd58f6859999faafcea60de686262
* @param {String|Node} obj.target | Блок который фиксируем
* @param {Boolean} obj.fixAtTop | Зафиксировать везде начиная с верха сайта
* @param {Boolean} obj.fixAfter | Зафиксировать после ухода этого блока за верх экрана
* @param {String} obj.fixUnderBlock |
* @param {String} obj.fixOverBlock |
* @param {Number} obj.marginBottom |
*/
export function Fixer(obj) {
var self = this;
if (typeof obj.target === 'string') {
this.target = document.querySelector(obj.target);
} else {
this.target = 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment