You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: support ion-infinite-scroll in a flex-direction: column-reverse scroll element #31602
A chat-style page lays the scroll element out bottom-up with ion-content::part(scroll) { display: flex; flex-direction: column-reverse; } so that the newest row sits at the bottom and the scroller starts there. In that layout the browser's scrollTop is 0 at the bottom and goes negative towards the top ([-320, 0] in the reproduction).
ion-infinite-scroll computes its distance as if scrollTop were non-negative (core/src/components/infinite-scroll/infinite-scroll.tsx L121–129):
With the trigger placed at the oldest end of the list (the last DOM child, painted at the top) and threshold="100px":
position
what happens
top
ionInfinite fires on the very first scroll step, 315 px away from the oldest end, and again on every later step (7 of 7 steps fired)
bottom
never fires, including at scrollTop = -320, i.e. with the trigger fully on screen at the oldest end
Scroller in the reproduction: scrollHeight 1164, clientHeight 844, so the whole scrollable range is 320 px.
connectedCallback (L96–101) and complete() (L184–200) also write scrollEl.scrollTop = scrollHeight - clientHeight / scrollHeight - prev for position="top", which are positions outside the [-320, 0] range of a column-reverse scroller.
Expected Behavior
The trigger fires once when the user is within threshold of the trigger element, whichever direction the scroll element grows in.
Steps to Reproduce
<ion-content> with the style above, 60 rows of 48 px, and <ion-infinite-scroll position="top" threshold="100px"> as the last child (so it paints at the top).
Listen to ionInfinite, call complete() in the handler, and set scrollTop to -5, -20, -60, … on the scroll element returned by getScrollElement().
Observe one ionInfinite per step. Switch to position="bottom" and scroll all the way up: no event.
changed the title [-]bug: ion-infinite-scroll fires continuously (position="top") or never (position="bottom") when the scroll element is `flex-direction: column-reverse`[/-][+]feat: support ion-infinite-scroll in a `flex-direction: column-reverse` scroll element[/+]on Oct 28, 2026
Verified on 9.0.10. Your analysis is right: ion-infinite-scroll measures its distance to the trigger as if scrollTop were never negative. In a column-reverse scroller it is 0 at the bottom and negative towards the top, so position="top" fires on every scroll and position="bottom" never fires. The scroll correction in complete() also writes positions outside the reversed range.
Workarounds, both verified on 9.0.10:
Keep the column-reverse scroller and replace ion-infinite-scroll with your own scroll listener. A reversed scroller keeps the visible messages in place when older ones are added, so no scroll correction is needed:
constcontent=document.querySelector('ion-content');constscrollEl=awaitcontent.getScrollElement();letloading=false;constloadOlderMessages=async()=>{// Fetch older messages and append them after the existing rows in the DOM};scrollEl.addEventListener('scroll',async()=>{constdistanceFromOldest=scrollEl.scrollHeight-scrollEl.clientHeight-Math.abs(scrollEl.scrollTop);if(loading||distanceFromOldest>100){return;}loading=true;awaitloadOlderMessages();loading=false;});
This replaces the earlier answer on #28182 that column-reverse is not supported. Keeping this open to track column-reverse support in ion-infinite-scroll.
Activity
[-]bug: ion-infinite-scroll fires continuously (position="top") or never (position="bottom") when the scroll element is `flex-direction: column-reverse`[/-][+]feat: support ion-infinite-scroll in a `flex-direction: column-reverse` scroll element[/+]thetaPC commentedon Oct 28, 2026
Thanks for the report!
Verified on 9.0.10. Your analysis is right:
ion-infinite-scrollmeasures its distance to the trigger as ifscrollTopwere never negative. In acolumn-reversescroller it is0at the bottom and negative towards the top, soposition="top"fires on every scroll andposition="bottom"never fires. The scroll correction incomplete()also writes positions outside the reversed range.Workarounds, both verified on 9.0.10:
column-reversescroller and replaceion-infinite-scrollwith your own scroll listener. A reversed scroller keeps the visible messages in place when older ones are added, so no scroll correction is needed:ion-infinite-scroll, use it withposition="top"in a normal scroller, withoutcolumn-reverse. That works today, though the list jumps briefly while older messages load, which is tracked in bug: infinite-scroll with position="top" causes flicker when restoring scroll position #28182.This replaces the earlier answer on #28182 that
column-reverseis not supported. Keeping this open to trackcolumn-reversesupport inion-infinite-scroll.