CDK virtual scroll with fixed item heights or a custom VirtualScrollStrategy for a variable-height Ionic feed
0 reputation · 01 Jun 2020, 00:46 UTC
0 reputation · 01 Jun 2020, 00:46 UTC
We are migrating an Ionic/Angular app away from the deprecated ion-virtual-scroll to Angular CDK's cdk-virtual-scroll-viewport, following the Ionic documentation's recommended path. The list in question is a chat-style feed where items mix short text messages, images, and preview cards, so heights vary significantly and some content loads asynchronously.
The constraint is that CDK's default itemSize strategy assumes a fixed, known height per item. Our options appear to be either normalizing every feed item to a fixed height (reserving aspect-ratio boxes for media) or writing a custom VirtualScrollStrategy that measures items dynamically. The first option changes our UI design; the second adds code we must maintain and test ourselves. We also plan to keep ion-infinite-scroll for pagination, so whichever approach we pick must compose cleanly with it.
Assume a current Ionic v7/v8 with a recent Angular version; we will confirm the exact deprecation status against our installed major version.
For teams that have made this migration: is a custom VirtualScrollStrategy for variable heights reliable enough in production mobile WebViews, or is enforcing fixed heights the pragmatic choice? Are there documented pitfalls with scroll-position stability when asynchronous images change measured heights? Does either approach interact differently with ion-infinite-scroll when new pages append at the bottom?
31775 reputation · 01 Jun 2020, 06:12 UTC
For a chat-style feed with mixed text, images, and preview cards, enforcing fixed (or at least pre-reserved) heights is the pragmatic default, and a custom VirtualScrollStrategy is only worth the maintenance cost if your design genuinely cannot reserve space for media. The deciding factor is not whether a custom strategy works — it does — but whether you can keep measured heights stable after render. If heights change after the viewport has positioned content, you get visible scroll jumps, and mobile WebViews make this worse, not better.
cdk-virtual-scroll-viewport with itemSize assumes every row has one known height. It computes total scroll extent as count × itemSize. In a feed where a one-line message might be 48px and an image card 320px, any single itemSize mis-sizes the scrollbar and causes drift between the rendered window and the scroll position. So your two candidate paths are the right ones; there is no third built-in option in current CDK versions.
Reserving aspect-ratio boxes for images and preview cards before the media loads is the key move. The item height is then known before render, so the default strategy works as designed:
line-clamp, or bucket into two or three fixed size classes if your design tolerates it.This eliminates the entire class of async-height bugs and composes trivially with ion-infinite-scroll: appending items just extends the array, and the extent math stays correct. The cost is UI compromise — short messages waste vertical space if you pick one height for everything.
A custom strategy that measures rendered items (via ResizeObserver or explicit measurement after change detection) is reliable in production if heights are stable once measured. The documented pitfall class you asked about is real: when an async image loads and changes an item's height above the current scroll offset, the content under the user's finger shifts. Mitigations:
Expect to own the test surface: scroll retention across pagination, font-size changes, and orientation changes on real devices, not just desktop Chrome.
Appending at the bottom is the friendly case for both approaches: new items extend the list past the current viewport, so existing offsets are unaffected. Two things to verify:
elementScrolled() / rendered range) rather than assuming ion-infinite-scroll sees the inner scroll element — depending on your DOM structure, the scrollable element is the viewport, not the ion-content. This is the most common integration bug in this migration.Given that your backend can supply media dimensions, I'd normalize: aspect-ratio placeholders plus a small set of text height classes, default itemSize strategy, done. Reserve the custom strategy for when design rejects clamping. Either way, verify on-device:
ion-virtual-scroll deprecation/removal status against your installed Ionic major (v7 vs v8) before scheduling the migration.One detail that would change this recommendation: if your backend cannot provide media dimensions up front, fixed heights become much harder and the custom strategy with delta-compensation becomes the better bet.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.