Skip to content

BUG: phx-viewport-bottom + infinite scroll causes poor UX. #3887

@lifeiscontent

Description

@lifeiscontent

Issue Summary

I've encountered a bug with the infinite scroll implementation in Phoenix LiveView while following the official documentation. The issue occurs when users refresh the page after scrolling partway through an infinite scroll list.

PR for reference: lifeiscontent/realworld_phoenix#1

Documentation followed: https://hexdocs.pm/phoenix_live_view/bindings.html#scroll-events-and-infinite-pagination

Bug Description

When implementing infinite scroll as documented, I use a large padding-bottom on the scroll container to trigger the phx-viewport-bottom hook. However, this creates a problematic user experience:

  1. User scrolls halfway down the page (loading more content via infinite scroll)
  2. User refreshes the browser
  3. Browser restores the scroll position to where they were
  4. The viewport hook doesn't trigger because the user is in the middle of the content
  5. User sees a blank white page due to the large padding-bottom
  6. User is confused and has to manually scroll up to see content

Current Implementation

Following the LiveView docs, I have:

<div
  id="articles"
  phx-update="stream"
  phx-viewport-bottom={!@end_of_feed? && JS.push("next-page")}
  class={[
    "mt-8 space-y-6",
    if(@end_of_feed?, do: "pb-10", else: "pb-[calc(200vh)]")
  ]}
>
  <!-- Stream items here -->
</div>

The pb-[calc(200vh)] padding is necessary to trigger the viewport hook, but causes this refresh issue.

Expected Behavior

When a user refreshes the page while scrolled partway through infinite scroll content:

  • The page should either reset to the top
  • Or restore the scroll position AND immediately load the visible content
  • The user should never see a blank white page

Reproduction

The PR linked above contains a full implementation that reproduces this issue. To see it in action:

  1. Clone the PR branch
  2. Run mix setup (this will create the database and seed it with sample articles)
  3. Run mix phx.server
  4. Navigate to http://localhost:4000/articles
  5. Scroll down to load 2-3 batches of content
  6. Refresh the browser (F5 or Cmd+R)
  7. Observe the blank white page with large padding

Potential Solutions

  1. Reset scroll on refresh: Force scroll position to top on page load
  2. Detect and handle restored scroll position: Check scroll position on mount and trigger content loading if needed
  3. Alternative infinite scroll approach: Perhaps using Intersection Observer API instead of large padding
  4. Documentation update: Add guidance on handling browser refresh scenarios

Environment

  • Phoenix LiveView 1.0.17
  • Phoenix 1.7.21
  • Elixir 1.18.4 (compiled with Erlang/OTP 27)
  • Erlang/OTP 27
  • Browser: All modern browsers (Chrome, Firefox, Safari)

Impact

This affects user experience significantly as users expect to be able to refresh a page without losing their place or seeing a broken interface. It's particularly problematic for content-heavy applications like blogs, social feeds, or article listings.

I'd appreciate guidance on the recommended approach to handle this scenario, or if this is something that could be addressed in Phoenix LiveView itself.

Thank you for your time and for creating such an excellent framework!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions