Stickybits — это легковесная библиотека для создания «липких» элементов на странице, которая управляет поведением элементов при прокрутке без необходимости ручной реализации сложной логики. В React интеграция требует внимательного подхода к жизненному циклу компонентов и правильного управления ссылками на DOM-элементы.
В React ключевым моментом является использование
ref для получения прямого доступа к DOM-элементу, который
нужно сделать «липким». Stickybits не работает напрямую с виртуальным
DOM, поэтому необходимо работать через реальный элемент.
import React, { useEffect, useRef } from 'react';
import stickybits from 'stickybits';
function StickyComponent() {
const stickyRef = useRef(null);
useEffect(() => {
const stickyInstance = stickybits(stickyRef.current, {
stickyBitStickyOffset: 0,
useStickyClasses: true
});
return () => {
stickyInstance.cleanup();
};
}, []);
return (
<div ref={stickyRef} className="sticky-element">
Липкий блок
</div>
);
}
В React важно корректно очищать Stickybits при удалении компонента. В
примере выше метод cleanup() вызывается внутри функции
очистки useEffect. Это предотвращает возможные утечки
памяти и некорректное поведение при повторном монтировании
компонента.
При инициализации Stickybits можно передавать объект конфигурации. Основные параметры:
stickyBitStickyOffset — смещение
элемента от верхнего края окна при фиксации. Может быть положительным
или отрицательным числом.useStickyClasses — добавление
CSS-классов js-is-sticky и js-is-stuck для
удобного управления стилями через CSS.verticalPosition — позиция элемента
(top или bottom) относительно окна.noStyles — если true,
библиотека не применяет встроенные стили, позволяя полностью управлять
внешним видом через CSS.stickybits(stickyRef.current, {
stickyBitStickyOffset: 10,
useStickyClasses: true,
verticalPosition: 'top',
noStyles: false
});
В React компоненты часто меняют размер или содержимое после рендера. В таких случаях рекомендуется перезапуск Stickybits после изменения высоты элемента:
useEffect(() => {
const stickyInstance = stickybits(stickyRef.current);
const resizeObserver = new ResizeObserver(() => {
stickyInstance.update();
});
resizeObserver.observe(stickyRef.current);
return () => {
resizeObserver.disconnect();
stickyInstance.cleanup();
};
}, []);
Использование ResizeObserver позволяет библиотеке
корректно реагировать на изменения размера и позиции элементов, что
особенно важно для адаптивного дизайна.
При использовании параметра useStickyClasses Stickybits
автоматически добавляет классы:
js-is-sticky — элемент стал
липким.js-is-stuck — элемент достиг нижней
границы контейнера.js-unsticky — элемент больше не
липкий.Это позволяет полностью отделить логику от визуального представления, управляя стилями через CSS:
.sticky-element {
transition: all 0.3s ease;
}
.js-is-sticky {
background-color: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.js-is-stuck {
opacity: 0.8;
}
Создание кастомного хука позволяет унифицировать интеграцию Stickybits:
import { useEffect, useRef } from 'react';
import stickybits from 'stickybits';
export function useSticky(options = {}) {
const ref = useRef(null);
useEffect(() => {
if (!ref.current) return;
const instance = stickybits(ref.current, options);
return () => {
instance.cleanup();
};
}, [options]);
return ref;
}
Применение в компоненте:
function Header() {
const stickyRef = useSticky({ stickyBitStickyOffset: 20, useStickyClasses: true });
return (
<header ref={stickyRef}>
Заголовок сайта
</header>
);
}
При переходе между маршрутами иногда необходимо повторная инициализация Stickybits, так как новые компоненты рендерятся заново. Использование хука с очисткой обеспечивает корректное поведение без «залипаний» и конфликтов классов.
ResizeObserver только для элементов с
динамической высотой.scroll или resize.Stickybits легко сочетается с библиотеками типа styled-components или emotion, так как CSS-классы можно использовать внутри стилей компонентов:
import styled from 'styled-components';
const StickyBox = styled.div`
padding: 16px;
background: #f5f5f5;
&.js-is-sticky {
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
background: #fff;
}
`;
function App() {
const stickyRef = useSticky({ useStickyClasses: true });
return <StickyBox ref={stickyRef}>Контент</StickyBox>;
}
Stickybits зависит от window и DOM, поэтому
нельзя вызывать библиотеку на сервере. Все вызовы
должны происходить внутри useEffect, который выполняется
только на клиенте. Это предотвращает ошибки в приложениях с серверным
рендерингом, таких как Next.js.