Headroom.js — это легковесная библиотека, которая управляет видимостью шапки страницы при скролле. В основе её работы лежит отслеживание направления и скорости прокрутки страницы. Библиотека предоставляет события, которые позволяют реагировать на появление и скрытие шапки, а также на начальное и окончательное движение скролла.
Ключевые события Headroom.js:
headroom:pin — вызывается, когда шапка фиксируется в
видимой позиции.headroom:unpin — вызывается, когда шапка скрывается при
прокрутке вниз.headroom:top — срабатывает, когда скролл достигает
верхней границы страницы.headroom:notTop — срабатывает, когда скролл уходит от
верхней границы.Эти события позволяют гибко интегрировать дополнительные эффекты и логику в зависимости от поведения пользователя на странице.
Для того чтобы отслеживать события, необходимо создать экземпляр Headroom.js и подключить к нему обработчики:
var header = document.querySelector("header");
var headroom = new Headroom(header, {
tolerance: 5,
offset: 100,
classes: {
initial: "headroom",
pinned: "headroom--pinned",
unpinned: "headroom--unpinned",
top: "headroom--top",
notTop: "headroom--not-top"
}
});
headroom.init();
// Привязка событий
header.addEventListener("headroom:pin", function() {
console.log("Шапка зафиксирована");
});
header.addEventListener("headroom:unpin", function() {
console.log("Шапка скрыта");
});
header.addEventListener("headroom:top", function() {
console.log("Скролл на вершине");
});
header.addEventListener("headroom:notTop", function() {
console.log("Скролл от верхней границы");
});
Особенности и тонкости:
tolerance отвечает за минимальное смещение, которое
учитывается перед срабатыванием pin/unpin. Значение может быть числом
или объектом с разными значениями для вверх и вниз:
{up: 5, down: 10}.offset задаёт точку, после которой шапка начнёт
скрываться при прокрутке вниз.Для полноценного дебаггинга необходимо отслеживать несколько аспектов:
requestAnimationFrame или
debounce/throttle из Lodash.Пример с throttle для оптимизации логирования:
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
}
}
header.addEventListener("headroom:pin", throttle(function() {
console.log("Оптимизированное событие pin");
}, 100));
Совместимость с другими библиотеками: если на
странице есть другие скрипты, которые меняют стили или позицию шапки,
события pin/unpin могут срабатывать
некорректно. В таких случаях важно проверять фактический класс элемента
через classList.contains.
Визуальный дебаггинг: можно добавлять временные визуальные метки при срабатывании событий:
.debug-marker {
position: fixed;
top: 0;
right: 0;
width: 20px;
height: 20px;
background-color: red;
z-index: 9999;
}
function createMarker(eventName) {
const marker = document.createElement("div");
marker.className = "debug-marker";
marker.title = eventName;
document.body.appendChild(marker);
setTimeout(() => marker.remove(), 500);
}
header.addEventListener("headroom:pin", () => createMarker("pin"));
header.addEventListener("headroom:unpin", () => createMarker("unpin"));
Помимо стандартных событий, полезно отслеживать:
header.offsetHeightwindow.scrollYЭто помогает выявлять, почему события могут срабатывать раньше или позже ожидаемого момента. Пример:
window.addEventListener("scroll", throttle(() => {
console.log("ScrollY:", window.scrollY, "Header height:", header.offsetHeight);
}, 50));
Для сложных интерфейсов важно убедиться, что:
offset и tolerance соответствуют
макету.pinned и unpinned
корректно применяются и не конфликтуют с другими стилями.null при выборе элемента.document.addEventListener("DOMContentLoaded", function() {
headroom.init();
});
Использование этих методов позволяет детально контролировать поведение шапки, понимать, какие события срабатывают и почему, и корректно интегрировать Headroom.js даже в сложные интерфейсы с динамическим контентом.