Одной из ключевых особенностей Locomotive Scroll
является его зависимость от точного измерения размеров контейнера для
корректной прокрутки. При изменении высоты элементов на странице —
например, при подгрузке изображений, асинхронном контенте или
раскрывающихся блоках — библиотека не обновляет внутренние данные
автоматически. Это приводит к неправильному отображению скролла, рывкам
или «зависанию» контента.
Важно понимать: Locomotive Scroll
фиксирует высоту контейнера при инициализации. Любое изменение размеров
элементов после этого момента требует ручного обновления.
Для корректного обновления высоты используется метод
update():
const scroll = new LocomotiveScroll({
el: document.querySelector('#js-scroll'),
smooth: true
});
// После изменения контента
scroll.update();
update() пересчитывает размеры контейнера и всех
дочерних элементов с атрибутами data-scroll,
data-scroll-speed, data-scroll-sticky и
другими.
Если контент меняется часто или динамически, рекомендуется вызывать
update() после каждого значительного
изменения DOM. Для оптимизации можно использовать
MutationObserver:
const observer = new MutationObserver(() => {
scroll.update();
});
observer.observe(document.querySelector('#js-scroll'), {
childList: true,
subtree: true
});
Изображения часто загружаются асинхронно, и их размеры неизвестны при
инициализации скролла. В результате высота контейнера определяется
некорректно. Один из способов решения — ожидание полной загрузки всех
изображений перед вызовом scroll.update():
const images = document.querySelectorAll('img');
let loadedImages = 0;
images.forEach(img => {
if (img.complete) {
loadedImages++;
} else {
img.addEventListener('load', () => {
loadedImages++;
if (loadedImages === images.length) {
scroll.update();
}
});
}
});
if (loadedImages === images.length) {
scroll.update();
}
Альтернативой является использование imagesLoaded или
других утилит для отслеживания загрузки картинок.
position: stickyЭлементы с position: sticky требуют корректного расчета
позиции внутри контейнера скролла. Если их родитель изменяет высоту
динамически, sticky-элементы могут «вылетать» за пределы контейнера.
Для предотвращения этого нужно после каждого изменения высоты родителя вызывать:
scroll.update();
или пересоздавать sticky-контекст:
scroll.destroy();
scroll = new LocomotiveScroll({
el: document.querySelector('#js-scroll'),
smooth: true
});
Частое использование scroll.update() при анимациях или
динамических списках может сильно нагрузить рендер. Рекомендуется:
update() только при значительных
изменениях DOM, а не на каждое событие.requestAnimationFrame для группировки
обновлений:let needsUpdate = false;
function onDomChange() {
if (!needsUpdate) {
needsUpdate = true;
requestAnimationFrame(() => {
scroll.update();
needsUpdate = false;
});
}
}
MutationObserver только на
ключевых контейнерах.Если внутри контейнера есть элементы с анимацией изменения высоты
(height или scaleY), Locomotive Scroll не
учитывает их изменение в реальном времени. Решение:
scroll.update() после окончания анимации.requestAnimationFrame в цикле анимации
для плавного пересчета:function animateHeight(element, targetHeight, duration) {
const startHeight = element.offsetHeight;
const startTime = performance.now();
function step(now) {
const progress = Math.min((now - startTime) / duration, 1);
element.style.height = startHeight + (targetHeight - startHeight) * progress + 'px';
scroll.update();
if (progress < 1) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}
scroll.update() после любого
изменения высоты контейнера или его элементов.MutationObserver
или события загрузки изображений.update() для улучшения
производительности.position: sticky и
анимированным блокам, их поведение напрямую зависит от корректного
обновления размеров контейнера.Этот подход минимизирует проблемы с «неправильной» высотой и позволяет сохранить плавность и точность работы Locomotive Scroll при любых динамических изменениях контента.