Адаптивное поведение

Библиотека Locomotive Scroll изначально ориентирована на создание плавного скроллинга с использованием трансформаций (transform) и виртуального позиционирования. Это накладывает определённые ограничения и требования при разработке адаптивных интерфейсов.

Адаптивность в контексте Locomotive Scroll включает:

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

Режимы работы: desktop vs mobile

Locomotive Scroll поддерживает разные конфигурации для десктопа и мобильных устройств через параметр smartphone и tablet.

const scroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: true,
  smartphone: {
    smooth: false
  },
  tablet: {
    smooth: false
  }
});

Особенности:

  • smooth: true — включает плавный скролл (через transform)
  • smooth: false — используется нативный скролл браузера

Причины отключения smooth на мобильных:

  • слабая производительность GPU
  • проблемы с инерцией скролла
  • несовместимость с системными жестами
  • увеличение расхода батареи

Breakpoints и медиазапросы

Locomotive Scroll не предоставляет встроенной системы брейкпоинтов, поэтому адаптивность реализуется через:

  • CSS media queries
  • JavaScript-логику

Пример ручного управления:

const isMobile = window.innerWidth < 768;

const scroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: !isMobile
});

Более гибкий подход:

function createScroll() {
  return new LocomotiveScroll({
    el: document.querySelector('[data-scroll-container]'),
    smooth: window.innerWidth > 1024
  });
}

let scroll = createScroll();

window.addEventListener('resize', () => {
  scroll.destroy();
  scroll = createScroll();
});

Ключевой момент:

При изменении размера окна необходимо пересоздавать экземпляр, а не просто менять параметры.


Управление resize-событиями

Locomotive Scroll не всегда корректно реагирует на изменение размеров контейнера. Требуется ручной вызов обновления:

window.addEventListener('resize', () => {
  scroll.update();
});

Когда использовать update():

  • изменение размеров блоков
  • динамическая загрузка контента
  • смена ориентации устройства
  • изменение шрифтов

Работа с мобильными устройствами

Отключение smooth-скролла

На мобильных устройствах рекомендуется:

smartphone: {
  smooth: false
}

Проблемы, которые это решает:

  • “рывки” при прокрутке
  • задержки отклика
  • проблемы с input-полями
  • некорректное поведение фиксированных элементов

Фиксированные элементы и адаптивность

Locomotive Scroll ломает стандартное поведение position: fixed, так как контейнер скролла трансформируется.

Решение: использовать data-scroll-sticky

<div data-scroll data-scroll-sticky data-scroll-target="#section">
  Фиксированный элемент
</div>

Особенности:

  • элемент фиксируется внутри заданного контейнера
  • корректно работает при разных разрешениях
  • требует точного указания data-scroll-target

Адаптация изображений и медиа

При использовании Locomotive Scroll важно учитывать:

  • lazy loading
  • пересчёт размеров
  • влияние transform на рендеринг

Пример:

<img data-scroll src="image.jpg" alt="">

После загрузки изображения:

imagesLoaded(document.querySelector('[data-scroll-container]'), () => {
  scroll.update();
});

Ключевой момент:

Без update() элементы могут отображаться с неправильными координатами.


Управление скоростью и эффектами

Скорость скролла может отличаться на разных устройствах.

<div data-scroll data-scroll-speed="2">
  Быстрый элемент
</div>

Рекомендации:

  • на мобильных уменьшать скорость
  • избегать больших значений (>3)
  • тестировать на слабых устройствах

Отключение эффектов для производительности

На мобильных устройствах или слабых ПК рекомендуется отключать тяжёлые эффекты:

const scroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: window.innerWidth > 768,
  lerp: window.innerWidth > 768 ? 0.1 : 1
});

Параметр lerp:

  • отвечает за плавность интерполяции
  • меньше значение → плавнее, но тяжелее
  • больше значение → быстрее, но менее плавно

Data-атрибуты и адаптивность

Locomotive Scroll активно использует data-атрибуты:

  • data-scroll
  • data-scroll-speed
  • data-scroll-direction
  • data-scroll-delay

Пример адаптации через JS:

if (window.innerWidth < 768) {
  document.querySelectorAll('[data-scroll-speed]').forEach(el => {
    el.removeAttribute('data-scroll-speed');
  });
}

Управление классами состояния

Locomotive Scroll добавляет классы:

  • is-inview
  • has-scroll-scrolling
  • has-scroll-smooth

Пример адаптивного поведения:

.has-scroll-smooth .menu {
  opacity: 0.8;
}

@media (max-width: 768px) {
  .menu {
    opacity: 1;
  }
}

Контейнеры и вложенность

Важно учитывать, что Locomotive Scroll работает с одним основным контейнером:

<div data-scroll-container>
  ...
</div>

Ошибки адаптации:

  • вложенные scroll-контейнеры
  • overflow внутри контейнера
  • фиксированные высоты

Рекомендация:

Использовать flex и auto-height, избегая жёстких размеров.


Интеграция с CSS Grid и Flexbox

Locomotive Scroll корректно работает с современными layout-системами, но:

Потенциальные проблемы:

  • изменение размеров элементов при скролле
  • пересчёт высоты контейнера

Решение:

scroll.on('scroll', () => {
  scroll.update();
});

(использовать осторожно из-за производительности)


Динамический контент

При добавлении элементов:

const newBlock = document.createElement('div');
newBlock.setAttribute('data-scroll', '');
document.querySelector('[data-scroll-container]').appendChild(newBlock);

scroll.update();

Без update:

  • элементы не будут отслеживаться
  • эффекты не применятся

Отключение Locomotive Scroll на малых экранах

Иногда проще полностью отказаться от библиотеки на мобильных:

let scroll = null;

function initScroll() {
  if (window.innerWidth > 1024) {
    scroll = new LocomotiveScroll({
      el: document.querySelector('[data-scroll-container]'),
      smooth: true
    });
  }
}

function destroyScroll() {
  if (scroll) {
    scroll.destroy();
    scroll = null;
  }
}

window.addEventListener('resize', () => {
  if (window.innerWidth <= 1024) {
    destroyScroll();
  } else if (!scroll) {
    initScroll();
  }
});

Производительность и адаптивность

Основные принципы:

  • минимизировать количество анимаций
  • избегать тяжёлых transform-эффектов
  • отключать эффекты на слабых устройствах
  • контролировать repaint и reflow

Диагностика:

  • DevTools Performance
  • FPS мониторинг
  • тестирование на реальных устройствах

Особенности iOS и Android

iOS:

  • проблемы с position: fixed
  • баги с инерцией
  • ограничения WebKit

Android:

  • разная производительность устройств
  • проблемы с GPU acceleration

Практика:

  • использовать нативный скролл
  • избегать сложных параллаксов
  • тестировать на нескольких устройствах

Синхронизация с другими библиотеками

При использовании вместе с:

  • анимациями
  • роутингом
  • lazy loading

необходимо:

scroll.update();

после каждого изменения DOM.


Контроль состояния скролла

scroll.on('scroll', (args) => {
  const scrollY = args.scroll.y;

  if (scrollY > 500 && window.innerWidth > 768) {
    // логика для десктопа
  }
});

Резюме ключевых подходов

  • отключение smooth на мобильных
  • пересоздание экземпляра при resize
  • обязательный scroll.update() при изменениях
  • адаптация data-атрибутов
  • контроль производительности
  • отказ от библиотеки на слабых устройствах