Infinite Scroll

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

Подключение библиотеки выполняется через CDN или локально:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>

После подключения создаётся Waypoint, который срабатывает при пересечении целевого элемента:

var infiniteScrollWaypoint = new Waypoint({
  element: document.getElementById('load-more-trigger'),
  handler: function(direction) {
    if (direction === 'down') {
      loadMoreContent();
    }
  },
  offset: '100%'
});

Здесь ключевые моменты:

  • element — элемент, который будет триггером подгрузки. Обычно это скрытый <div> в конце контента.
  • handler — функция, выполняемая при достижении точки.
  • direction — направление прокрутки ('down' или 'up').
  • offset — расстояние от верха видимой области, при котором срабатывает событие. Можно указывать в процентах или пикселях.

Настройка оффсета и контроль частоты срабатываний

Offset позволяет запускать загрузку заранее, чтобы пользователь не заметил задержку при прокрутке. Например, значение '90%' запустит подгрузку чуть выше нижней границы экрана:

offset: '90%'

Чтобы избежать многократных срабатываний при быстром скролле, используют флаг загрузки:

var loading = false;

function loadMoreContent() {
  if (loading) return;
  loading = true;

  $.ajax({
    url: '/load-more',
    method: 'GET',
    success: function(data) {
      $('#content').append(data);
      loading = false;
    }
  });
}

Таким образом, пока идёт загрузка данных, новые вызовы обработчика блокируются.


Комбинирование с пагинацией и API

Для бесконечной прокрутки часто требуется поддержка постраничной загрузки через API. В этом случае сохраняют текущую страницу и увеличивают её при каждом срабатывании Waypoint:

var currentPage = 1;

function loadMoreContent() {
  if (loading) return;
  loading = true;

  $.ajax({
    url: `/api/posts?page=${currentPage + 1}`,
    method: 'GET',
    success: function(data) {
      if (data.length > 0) {
        $('#posts-container').append(data);
        currentPage++;
        loading = false;
      } else {
        infiniteScrollWaypoint.destroy();
      }
    }
  });
}

Метод destroy() удаляет Waypoint после того, как больше данных нет, чтобы не висел «лишний» обработчик.


Динамическая пересоздание Waypoints

При подгрузке контента размер страницы меняется, и иногда требуется пересоздавать Waypoints или обновлять их расчёт:

Waypoints.refreshAll();

Этот метод пересчитывает позиции всех созданных Waypoints, что важно при добавлении элементов динамически.


Использование Sticky и Infinite Scroll вместе

Waypoints поддерживает sticky элементы, которые остаются фиксированными в определённой позиции при скролле. Это удобно для фиксации кнопки «Подгрузить ещё» или навигации:

$('#sticky-header').waypoint('sticky', {
  offset: 0
});

Комбинация sticky и infinite scroll позволяет:

  • Поддерживать элементы управления видимыми при загрузке контента.
  • Создавать плавный UX без резких прыжков при добавлении новых блоков.

Оптимизация производительности

При реализации бесконечной прокрутки важно учитывать производительность:

  1. Дебаунс обработчика – ограничение частоты вызовов:
var handler = _.throttle(function() {
  loadMoreContent();
}, 200);
  1. Удаление неиспользуемых Waypoints – после достижения конца списка.
  2. Загрузка контента порциями – 10–20 элементов за раз, чтобы не перегружать DOM.
  3. Lazy-loading изображений – для снижения веса страницы при добавлении новых блоков.

Поддержка нескольких точек подгрузки

Иногда необходимо иметь несколько триггеров на одной странице, например, для разных секций контента. Waypoints позволяет создавать несколько экземпляров:

var section1Waypoint = new Waypoint({
  element: document.getElementById('section1-trigger'),
  handler: function() { loadSection1(); },
  offset: '80%'
});

var section2Waypoint = new Waypoint({
  element: document.getElementById('section2-trigger'),
  handler: function() { loadSection2(); },
  offset: '80%'
});

Каждый Waypoint работает независимо, обеспечивая гибкость для сложных страниц с различными потоками контента.


События Waypoints

Waypoints предоставляет дополнительные события, полезные для отладки и аналитики:

  • waypoint.trigger — срабатывает при достижении элемента.
  • waypoint.destroy — удаление Waypoint.
  • waypoint.disable/enable — временная блокировка или включение обработчика.

Пример отслеживания срабатываний:

var wp = new Waypoint({
  element: document.getElementById('load-more-trigger'),
  handler: function(direction) {
    console.log('Waypoint сработал, направление:', direction);
  }
});

Это помогает видеть поведение скролла и корректно настраивать offset и флаги загрузки.


Waypoints в связке с AJAX и API обеспечивает надёжную, гибкую и оптимизированную бесконечную прокрутку, позволяя подгружать контент заранее, управлять состояниями загрузки и поддерживать производительность страницы.