Skip to content

Instantly share code, notes, and snippets.

@artemsites
Last active October 31, 2023 14:31
Show Gist options
  • Save artemsites/130fd58f6859999faafcea60de686262 to your computer and use it in GitHub Desktop.
Save artemsites/130fd58f6859999faafcea60de686262 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.6 - 31.10.2023
* @author Artem Kuznecov
* @email info@artemsites.ru
* @website https://artemsites.ru
* @source https://snippets.cacher.io/snippet/79e169f9ca705c345531
* @source https://gist.github.com/artemijeka/130fd58f6859999faafcea60de686262
* @param {String|Node} obj.target | Блок который фиксируем
*
* Класс --fixed просто добавляется без style изменений (для гибкости)
* @param {Boolean} obj.fixAtTop | Зафиксировать везде начиная с верха сайта
*
* @param {Boolean} obj.fixAfter | Зафиксировать после ухода этого блока за верх экрана
* @param {Array} obj.addClass | Добавить класс к какому-то элементу - addClass: ['.header', '_header-fixed']
* @param {String} obj.fixUnderBlock |
* @param {String} obj.fixOverBlock |
* @param {Number} obj.marginBottom |
*/
/**
new Fixer({
target: '.header__self',
fixAtTop: true,
addClass: ['.header', '_header-fixed']
});
*/
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;
if (obj.addClass) {
this.elAddClass = document.querySelector(obj.addClass[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.classList.add('--fixed');
if (self.elAddClass) self.elAddClass.classList.add(obj.addClass[1]);
self.fixed = true;
} else if (
self.fixed &&
self.windowOfTop < self.targetOffsetTopFixed
) {
self.target.classList.remove('--fixed');
if (self.elAddClass) self.elAddClass.classList.remove(obj.addClass[1]);
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