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

Open
#3,887 3 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
elixir
Domain
frontend, web-dev

Research direction

Start with the linked reproduction PR and the official Phoenix LiveView scroll-events and infinite-pagination documentation. Run the reproduction at /articles, follow the listed setup and scrolling steps, and compare the refresh behavior with the expected handling of restored scroll position. Done means an agreed approach prevents the blank page without relying on an unresolved alternative.

Written by the indexing model from the issue text.

Description

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: https://github.com/lifeiscontent/realworld_phoenix/pull/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!

Dominant language
Elixir
Stars
6.8k
Forks
1.1k
Avg merge
1d 3h
Merged PRs (30d)
19

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from phoenixframework/phoenix_live_view

All issues in phoenixframework/phoenix_live_view

Similar issues

More Elixir issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.