BUG: phx-viewport-bottom + infinite scroll causes poor UX.
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 25/100
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:
- User scrolls halfway down the page (loading more content via infinite scroll)
- User refreshes the browser
- Browser restores the scroll position to where they were
- The viewport hook doesn't trigger because the user is in the middle of the content
- User sees a blank white page due to the large padding-bottom
- 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:
- Clone the PR branch
- Run
mix setup(this will create the database and seed it with sample articles) - Run
mix phx.server - Navigate to http://localhost:4000/articles
- Scroll down to load 2-3 batches of content
- Refresh the browser (F5 or Cmd+R)
- Observe the blank white page with large padding
Potential Solutions
- Reset scroll on refresh: Force scroll position to top on page load
- Detect and handle restored scroll position: Check scroll position on mount and trigger content loading if needed
- Alternative infinite scroll approach: Perhaps using Intersection Observer API instead of large padding
- 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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from phoenixframework/phoenix_live_view
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
phoenixframework/phoenix_live_view#4509 ·
Maintainers usually reply within 1 day
-
awaiting feedback needs more info
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
phoenixframework/phoenix_live_view#4407 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
phoenixframework/phoenix_live_view#4507 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
phoenixframework/phoenix_live_view#4506 ·
Maintainers usually reply within 1 day
-
Focused input with `phx-patch-focused` loses typed chars when a `phx-change` reply lands mid-typingOpen
Difficulty 4/5 3-5 days Newbie friendliness 65/100
phoenixframework/phoenix_live_view#4504 ·
Maintainers usually reply within 1 day
All issues in phoenixframework/phoenix_live_view
Similar issues
-
Bug: Table layout and date column are cut off on mobile screens on the Tournaments -> History pageOpenbug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
hexlet-codebattle/codebattle#2375 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
wintermeyer/vutuv#2388 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
Broadcast API docs say to prepend realtime: to the topic, which breaks deliveryPossibly taken @mandar1045 claimed this 1 day ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 80/100
Maintainers usually reply within 1 day
-
camelToSnake and snakeCamelMapper() drop the underscore when a digit precedes a camelCase boundaryOpen
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
electric-sql/electric#4855 ·