Использование в Vue.js

Для интеграции Headroom.js в Vue.js проект сначала необходимо установить библиотеку через npm:

npm install headroom.js

После установки создается возможность использовать Headroom напрямую либо обернув его в собственный Vue-компонент. Основная цель Headroom — управлять видимостью элементов интерфейса при прокрутке страницы, чаще всего это заголовки (header) или панели навигации.

Создание собственного Vue-компонента с Headroom

Для удобного использования 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-логику.

Интеграция с динамическими данными Vue

Headroom хорошо работает вместе с реактивными свойствами Vue. Например, можно условно изменять offset или управлять поведением через computed свойства:

computed: {
  headerOffset() {
    return this.isLoggedIn ? 100 : 50;
  }
},
watch: {
  headerOffset(newOffset) {
    if (this.headroom) {
      this.headroom.offset = newOffset;
      this.headroom.update();
    }
  }
}

Такой подход позволяет адаптировать поведение заголовка под состояние приложения, например, когда добавляется дополнительная панель уведомлений.

Использование с Vue Router

При переходе между страницами важно корректно обновлять состояние Headroom. Для SPA-приложений на Vue Router это можно сделать через наблюдение за изменением маршрута:

watch: {
  $route() {
    if (this.headroom) {
      this.headroom.destroy();
      this.headroom.init();
    }
  }
}

Это гарантирует, что элементы интерфейса на новых страницах будут корректно реагировать на скролл.

Подключение через директиву Vue

Для более декларативного подхода можно создать кастомную директиву 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 только на видимых страницах и удалять при переходах, чтобы избежать утечек памяти.

Комбинирование с CSS-фреймворками

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, чтобы сразу видеть готовый рабочий код. Это даст полноценную демонстрацию использования в реальном приложении.