Синхронизация нескольких headroom-элементов

Для работы с несколькими элементами, которые должны скрываться и отображаться при скролле, необходимо создать отдельный экземпляр Headroom для каждого элемента. Headroom.js не предоставляет встроенной поддержки групповой синхронизации, поэтому синхронизацию действий придется реализовать вручную.

Пример базового подключения нескольких элементов:

const headerMain = document.querySelector('#header-main');
const headerSecondary = document.querySelector('#header-secondary');

const headroomMain = new Headroom(headerMain, {
    tolerance: 5,
    offset: 50,
    classes: {
        initial: 'headroom',
        pinned: 'headroom--pinned',
        unpinned: 'headroom--unpinned',
        top: 'headroom--top',
        notTop: 'headroom--not-top'
    }
});

const headroomSecondary = new Headroom(headerSecondary, {
    tolerance: 5,
    offset: 50,
    classes: {
        initial: 'headroom',
        pinned: 'headroom--pinned',
        unpinned: 'headroom--unpinned',
        top: 'headroom--top',
        notTop: 'headroom--not-top'
    }
});

headroomMain.init();
headroomSecondary.init();

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


Синхронизация состояний

Для синхронизации требуется слушать события onPin и onUnpin каждого экземпляра и вручную вызывать соответствующие методы у других элементов:

headroomMain.options.on Pin = function() {
    headroomSecondary.pin();
};

headroomMain.options.onUn pin = function() {
    headroomSecondary.unpin();
};

Таким образом, когда главный хедер фиксируется (pin), вторичный также фиксируется, а при скрытии (unpin) — вторичный скрывается синхронно.

Можно расширить эту логику для произвольного количества элементов, используя массив:

const headers = [
    document.querySelector('#header-main'),
    document.querySelector('#header-secondary'),
    document.querySelector('#header-tertiary')
];

const headrooms = headers.map(header => new Headroom(header, {
    tolerance: 5,
    offset: 50
}));

headrooms.forEach(hr => hr.init());

headrooms[0].options.on Pin = function() {
    headrooms.slice(1).forEach(hr => hr.pin());
};

headrooms[0].options.onUn pin = function() {
    headrooms.slice(1).forEach(hr => hr.unpin());
};

Совмещение разных конфигураций

Каждому элементу можно задать собственные настройки tolerance и offset, что позволяет создавать гибкие взаимодействия. Например, главный хедер может реагировать на прокрутку быстрее, а вторичный — с задержкой:

const headroomMain = new Headroom(headerMain, { tolerance: 10, offset: 100 });
const headroomSecondary = new Headroom(headerSecondary, { tolerance: 5, offset: 200 });

События onPin и onUnpin можно использовать для выравнивания анимаций, например, добавляя задержку через setTimeout:

headroomMain.options.on Pin = function() {
    setTimeout(() => headroomSecondary.pin(), 100);
};

headroomMain.options.onUn pin = function() {
    setTimeout(() => headroomSecondary.unpin(), 100);
};

Обработка конфликтов скролла

Если элементы находятся на разных уровнях документа или имеют разные высоты, синхронизация через стандартные события pin/unpin может вызывать мерцание. Для устранения конфликтов следует использовать вычисление текущего скролла:

window.addEventListener('scroll', () => {
    const scrollY = window.scrollY;
    if (scrollY > 150) {
        headrooms.forEach(hr => hr.pin());
    } else {
        headrooms.forEach(hr => hr.unpin());
    }
});

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


Использование с CSS-анимациями

Для плавной синхронизации рекомендуется комбинировать headroom--pinned и headroom--unpinned с CSS-переходами:

.headroom--pinned {
    transform: translateY(0);
    transition: transform 0.3s ease-in-out;
}

.headroom--unpinned {
    transform: translateY(-100%);
    transition: transform 0.3s ease-in-out;
}

С помощью единых классов анимации будут согласованно применяться ко всем синхронизированным элементам.


Динамическое добавление элементов

Если на странице появляются новые блоки после загрузки (например, подгруженные через AJAX), их можно добавить в массив headrooms и инициализировать:

const newHeader = document.querySelector('#header-new');
const newHeadroom = new Headroom(newHeader, { tolerance: 5, offset: 50 });
newHeadroom.init();
headrooms.push(newHeadroom);

Чтобы синхронизация сохранялась, нужно добавить обработку onPin/onUnpin аналогично существующим элементам.


Резюме ключевых техник

  • Каждый элемент требует отдельного экземпляра Headroom.
  • События onPin и onUnpin позволяют синхронизировать состояния нескольких элементов.
  • Массивы и методы forEach упрощают масштабирование до произвольного числа элементов.
  • Настройки tolerance и offset можно комбинировать для создания сложных визуальных эффектов.
  • Использование CSS-переходов обеспечивает плавную анимацию всех синхронизированных элементов.
  • Для динамически добавляемых элементов необходимо повторно инициализировать Headroom и интегрировать их в систему синхронизации.