Skip to content
PПромтбук
RUEN
02UX-флоу

Infinite scroll vs pagination: что выбрать

Decision matrix по контексту контента, deep linking, accessibility, back-button, performance. Без «бесконечный скролл потому что современно».

Действуй как senior UX-инженер. Выбор pagination vs infinite scroll — это компромисс между discovery и retrievability. Не «современно vs устаревше». У каждого паттерна есть домены, где он провален.

Контент: {{content_type}} Возврат к элементу: {{return_pattern}} Цель: {{discoverability}}

Decision matrix

СценарийPaginationInfinite scrollГибрид (Load more)
Feed / timeline (Twitter, Instagram)✗ ломает контекст✓ оптимально
Search results✓ возврат к page-N✗ нет return
Catalog (e-commerce)✓ standard△ требует deep links✓ часто лучше
Data table✓ всегда✗ a11y disaster
Activity log✓ для audit✓ для casual browse
Comments / replies✗ ломает thread△ для коротких✓ оптимально
Media gallery✓ если discovery

Когда infinite scroll работает

  1. Discovery без цели. Юзер scroll'ит без конкретного «найти X». Examples: Instagram, Pinterest, TikTok.
  2. Контент = развлечение/новости. Каждый элемент самодостаточен, возврат не нужен.
  3. Mobile-first. Тапать «next page» на мобильном — boilerplate. Scroll естественен.
  4. Real-time updates (Twitter timeline). Pagination не работает с непрерывным потоком.

Когда infinite scroll НЕ работает

  1. Юзер должен вернуться к конкретному элементу. Search results, catalog, data table. Refresh / back → теряется place.
  2. Footer нужен и нужен достижимый. Infinite scroll буквально убивает footer (его не достигают).
  3. Accessibility critical. Screen reader юзеры не могут навигировать по бесконечно растущему списку.
  4. Compare между result'ами. Юзер не может «отскролл back to result #14».
  5. Сlear scope. «Found 247 items» — юзер хочет знать сколько всего. Infinite не показывает.

Pagination — анатомия

[< Prev]   1   2   [3]   4   5   ...   Last   [Next >]
  • Кнопки prev/next — отдельные, не в общей нумерации.
  • Текущая page — visible-different (filled).
  • First / Last — особенно для больших списков (юзер хочет «к концу»).
  • «...» для middle range при многих pages.
  • URL persistence: ?page=2. Browser back возвращает к page-2.

Page size

  • 25 / 50 / 100 — toggle в toolbar.
  • Default по контексту: 25 для search, 50 для catalog, 100 для admin tables.
  • Persist выбор в localStorage.

Loading state

  • Skeleton-список того же размера, что и предыдущая page.
  • НЕ spinner overlay (теряется контекст).
  • Page-change scroll: к началу нового списка (не к началу страницы — это запутает).

Infinite scroll — анатомия

[item 1]
[item 2]
...
[item N]
─────────────
[loading indicator]    ← пока подгружается
─────────────
[item N+1]
[item N+2]

Триггер подгрузки

  • IntersectionObserver на «sentinel» в 200-500px от низа списка. Pre-fetch.
  • НЕ scroll-event с throttle — это устарело.

Loading indicator

  • Skeleton-строки в районе подгрузки (3-5 штук).
  • Если ошибка — inline message «Couldn't load more. [Retry]».

End of list

  • Явный markup: «You've reached the end» / «No more items» / «That's all from <date>».
  • Без этого юзер scroll'ит и не понимает, кончилось ли.

Restore position

  • Если юзер кликает на item → navigates away → back → должен вернуться на тот scroll position.
  • В React Router / Next — restoration scroll API.
  • Хранить scroll position + loaded count в session/URL state.

Гибрид: «Load more» button

Лучший из миров для catalog / activity:

[item 1]
[item 2]
...
[item 20]

   [ Load more (20 of 247) ]
  • Юзер контролирует загрузку.
  • Footer достижим.
  • Можно показать count (X of Y).
  • Возврат к месту работает без сложной scroll-restoration.

Используй когда: список ограниченный (≤ 500 items), discovery + retrievability в равной мере.

URL и shareability

ПаттернURL behavior
Pagination?page=2 — share / back / refresh работает
Infinite scroll?cursor=xyz или нет URL state — share возвращает к началу
Load more?show=80 или ?cursor=xyz — work-around для share

Если share важен — pagination или гибрид. Чистый infinite scroll — не share-friendly.

A11y

Pagination

  • <nav aria-label="Pagination"> обёртка.
  • Текущая страница aria-current="page".
  • Prev / next — <a> или <button> с aria-label «Previous page».

Infinite scroll

  • aria-live="polite" на container'е для announce новых items.
  • «End of list» message с role="status".
  • Skip-link к началу / поиску.
  • Альтернатива «View as paginated» для assistive-tech юзеров (если возможно).

Performance

Pagination

  • Server-side с cursor (offset устарел для больших dataset'ов).
  • Pre-fetch следующей page on hover prev/next.

Infinite scroll

  • Virtualization обязательна при >100 загруженных items (react-virtual, tanstack-virtual).
  • DOM не должен расти бесконечно — иначе ноут плавится через 5 минут scroll'а.
  • Trim items вне viewport (windowing).

Формат вывода

Решение

Одна строка: «<pagination / infinite / load more> — потому что <2 главных критерия>».

Spec выбранного паттерна

Если pagination:

  • Page size (default + toggle options)
  • Pagination UI structure
  • URL scheme
  • Loading state

Если infinite scroll:

  • Trigger (sentinel + offset)
  • Loading indicator
  • End-of-list message
  • Scroll restoration
  • Virtualization (от какого count'а)

Если гибрид:

  • Initial count
  • Load more count per click
  • Counter «X of Y»

Mobile-адаптация

Что меняется.

A11y чеклист

ARIA, keyboard, скрытая «paginate view» (если есть).

Альтернатива

Если выбран infinite — где запасной pagination view (например, для filtered subset).

Anti-patterns (НЕ делать)

  • ❌ Infinite scroll на data table. Юзер хочет вернуться к row #234 — не может.
  • ❌ Infinite scroll без end-of-list message. Юзер не знает, кончилось ли.
  • ❌ Infinite scroll без virtualization при тысячах items. Memory leak, frozen UI.
  • ❌ Pagination без URL. Share-link → page 1.
  • ❌ Pagination, в котором current page визуально не отличается. «What page am I on?»
  • ❌ Footer на странице с infinite scroll. Он недостижим.
  • ❌ Infinite scroll на admin / data tables, где юзер сортирует и сравнивает. Невозможно.
  • ❌ «Load more» без счёта. Юзер не знает, сколько всего.
  • ❌ Infinite scroll без restore scroll position. Click → back → начало списка.
  • ❌ Infinite scroll, который добавляет новые items сверху во время чтения. Юзер теряет место.
К подразделу «UX-флоу»
Похожие промты