Для интеграции Headroom.js в Vue.js проект сначала необходимо установить библиотеку через npm:
npm install headroom.js
После установки создается возможность использовать Headroom напрямую
либо обернув его в собственный Vue-компонент. Основная цель Headroom —
управлять видимостью элементов интерфейса при прокрутке страницы, чаще
всего это заголовки (header) или панели навигации.
Для удобного использования Headroom в Vue.js целесообразно создать отдельный компонент, который инкапсулирует логику появления и скрытия элемента при скролле.
<template>
<header ref="header" class="header">
<slot></slot>
</header>
</template>
<script>
import Headroom from "headroom.js";
export default {
name: "HeadroomHeader",
mounted() {
const header = this.$refs.header;
this.headroom = new Headroom(header, {
tolerance: {
up: 10,
down: 5
},
offset: 50,
classes: {
initial: "headroom",
pinned: "headroom--pinned",
unpinned: "headroom--unpinned",
top: "headroom--top",
notTop: "headroom--not-top",
bottom: "headroom--bottom",
notBottom: "headroom--not-bottom"
}
});
this.headroom.init();
},
beforeUnmount() {
if (this.headroom) {
this.headroom.destroy();
}
}
};
</script>
<style scoped>
.headroom {
transition: transform 0.3s ease-in-out;
}
.headroom--unpinned {
transform: translateY(-100%);
}
.headroom--pinned {
transform: translateY(0);
}
</style>
tolerance — определяет, насколько должен измениться
скролл для срабатывания скрытия или показа. Можно задавать отдельные
значения для движения вверх (up) и вниз
(down).
offset — смещение в пикселях, после которого Headroom начнет реагировать на скролл.
classes — ключевой параметр, позволяющий задать CSS-классы для разных состояний:
initial — начальное состояние элемента;pinned — элемент видим, «приклеен» к верхней части
окна;unpinned — элемент скрыт, когда пользователь скроллит
вниз;top / notTop — находятся ли мы в верхней
части страницы;bottom / notBottom — для обработки
нахождения внизу страницы.Такое разделение классов обеспечивает гибкую стилизацию через CSS и возможность анимаций без вмешательства в JS-логику.
Headroom хорошо работает вместе с реактивными свойствами Vue. Например, можно условно изменять offset или управлять поведением через computed свойства:
computed: {
headerOffset() {
return this.isLoggedIn ? 100 : 50;
}
},
watch: {
headerOffset(newOffset) {
if (this.headroom) {
this.headroom.offset = newOffset;
this.headroom.update();
}
}
}
Такой подход позволяет адаптировать поведение заголовка под состояние приложения, например, когда добавляется дополнительная панель уведомлений.
При переходе между страницами важно корректно обновлять состояние Headroom. Для SPA-приложений на Vue Router это можно сделать через наблюдение за изменением маршрута:
watch: {
$route() {
if (this.headroom) {
this.headroom.destroy();
this.headroom.init();
}
}
}
Это гарантирует, что элементы интерфейса на новых страницах будут корректно реагировать на скролл.
Для более декларативного подхода можно создать кастомную директиву
v-headroom, которая автоматически инициализирует Headroom
для любого элемента:
import Headroom from "headroom.js";
export default {
mounted(el, binding) {
const options = binding.value || {};
const headroom = new Headroom(el, options);
headroom.init();
el._headroomInstance = headroom;
},
unmounted(el) {
if (el._headroomInstance) {
el._headroomInstance.destroy();
delete el._headroomInstance;
}
}
};
Использование в шаблоне:
<header v-headroom="{ offset: 60, tolerance: { up: 5, down: 5 } }">
Меню
</header>
Такой подход упрощает многократное использование Headroom без необходимости создания отдельных компонентов.
transform: translateY() вместо изменения
top или margin, чтобы включить
GPU-ускорение.tolerance и
offset без необходимости, чтобы минимизировать нагрузку при
скролле.Headroom легко интегрируется с Tailwind CSS или Vuetify. Например,
при использовании Tailwind достаточно заменить стили
.headroom--unpinned и .headroom--pinned на
классы -translate-y-full и translate-y-0.
Для Vuetify можно использовать Headroom для v-app-bar и
управлять его видимостью без изменения стандартного поведения
компонентов, добавив директиву или компонент-обертку.
Если необходимо, я могу написать полный пример проекта на Vue 3 с Headroom.js, включая интеграцию с Tailwind CSS и Vue Router, чтобы сразу видеть готовый рабочий код. Это даст полноценную демонстрацию использования в реальном приложении.