{"id":17056067,"url":"https://github.com/hoebbelsb/rxa-virtual-scroll","last_synced_at":"2025-07-30T11:37:53.703Z","repository":{"id":152714565,"uuid":"625061550","full_name":"hoebbelsB/rxa-virtual-scroll","owner":"hoebbelsB","description":"High performance angular virtual scrolling","archived":false,"fork":false,"pushed_at":"2023-10-20T12:50:39.000Z","size":5584,"stargazers_count":17,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-12T17:44:31.768Z","etag":null,"topics":["angular","virtual-scroll"],"latest_commit_sha":null,"homepage":"https://hoebbelsb.github.io/rxa-virtual-scroll/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hoebbelsB.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-04-08T00:47:48.000Z","updated_at":"2024-11-11T17:17:17.000Z","dependencies_parsed_at":"2024-04-07T22:00:37.906Z","dependency_job_id":null,"html_url":"https://github.com/hoebbelsB/rxa-virtual-scroll","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hoebbelsB/rxa-virtual-scroll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoebbelsB%2Frxa-virtual-scroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoebbelsB%2Frxa-virtual-scroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoebbelsB%2Frxa-virtual-scroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoebbelsB%2Frxa-virtual-scroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hoebbelsB","download_url":"https://codeload.github.com/hoebbelsB/rxa-virtual-scroll/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoebbelsB%2Frxa-virtual-scroll/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267858763,"owners_count":24155958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","virtual-scroll"],"created_at":"2024-10-14T10:23:13.691Z","updated_at":"2025-07-30T11:37:53.675Z","avatar_url":"https://github.com/hoebbelsB.png","language":"TypeScript","readme":"# RxAngular Virtual Scrolling Playground\n\n\u003e This is a playground/development repository. It served to test out ideas and concepts. It also hosts a demo application\n\n\u003e The code you see here is the latest version of the currently existing [PR](https://github.com/rx-angular/rx-angular/pull/1539) on rxa, just copied over to serve the demo with the latest version.\n\n# RxAngular Virtual Scrolling\n\nA **high performance** alternative to [`@angular/cdk/scrolling`](https://material.angular.io/cdk/scrolling/) virtual scrolling implementation.\n\n![rxa-vs-cdk](docs/images/rxa-vs-cdk.png)\n\nInstead of rendering every item provided, `rxVirtualFor` only renders what is currently visible to the user, thus providing\nexcellent runtime performance for huge sets of data.\n\nThe technique to render items is comparable to the one used by twitter and\nexplained in great detail by @DasSurma in his blog post about the\n[complexities of infinite scrollers](https://developer.chrome.com/blog/infinite-scroller/).\n\n\"Each recycling of a DOM element would normally relayout the entire runway which would bring us well below our target\nof 60 frames per second. To avoid this, we are taking the burden of layout onto ourselves and use absolutely positioned\nelements with transforms.\" [(@DasSurma)](https://twitter.com/dassurma)\n\n\u003e **⚠ Notice:**\n\u003e This package is currently experimental, the public API can potentially change\n\nThe `@rx-angular/template/experimental/virtual-scrolling` package is a high performant alternative of the official `@angular/cdk/scrolling`.\nThe API is heavily inspired by `@angular/cdk/scrolling` and is divided into multiple\ncore components which have to be glued together:\n\n- `RxVirtualViewRepeater`, implemented by `RxVirtualFor`\n- `RxVirtualScrollViewport`, implemented by `RxVirtualScrollViewportComponent`\n- `RxVirtualScrollStrategy`, implemented by `AutosizeVirtualScrollStrategy`, `\n\n# TOC\n\n[//]: # '* [Installation](#installation)'\n\n- [Usage](#usage)\n- [Demo](#demo)\n- [Features](#features)\n- [Performance Benchmarks](#performance-benchmarks)\n\n## Usage\n\n```ts\nimport {\n  FixedSizeVirtualScrollStrategy, // choose any strategy you like\n  RxVirtualScrollViewportComponent,\n  RxVirtualFor,\n} from '@rx-angular/template/experimental/virtual-scrolling';\n\n@Component({\n  standalone: true,\n  imports: [RxVirtualFor, RxVirtualScrollViewportComponent, FixedSizeVirtualScrollStrategy],\n})\nexport class MyComponent {}\n```\n\n```html\n\u003crx-virtual-scroll-viewport\u003e\n  \u003cdiv [itemSize]=\"50\" *rxVirtualFor=\"let hero of heroes$;\"\u003e\n    \u003cdiv\u003e\n      \u003cdiv\u003e\u003cstrong\u003e{{ hero.name }}\u003c/strong\u003e\u003c/div\u003e\n      \u003cdiv\u003e{{ hero.id }}\u003c/div\u003e\n      \u003cdiv\u003e{{ hero.description }}\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/rx-virtual-scroll-viewport\u003e\n```\n\n## Demo\n\nCheck out the [Demo Application](https://hoebbelsb.github.io/rxa-virtual-scroll/). You can play around with\nall pre-packaged ScrollStrategies as well as control the majority of inputs.\n\n## Features\n\n**DX Features**\n\n- reduces boilerplate (multiple `async` pipe's)\n- works also with static variables `*rxVirtualFor=\"let i of myData\"`\n- Immutable as well as mutable data structures (`trackBy`)\n- Notify when rendering of templates is finished (`renderCallback`)\n\n**Performance Features**\n\n- lazy template creation (done by [Render Strategies](https://www.rx-angular.io/docs/cdk/render-strategies))\n- non-blocking rendering of lists [Concurrent Strategies](https://www.rx-angular.io/docs/cdk/render-strategies/strategies/concurrent-strategies)\n- configurable frame budget (defaults to 60 FPS)\n- Super efficient layouting with css transformations\n- Scoped layouting with css containment\n- Define a viewCache in order to re-use views instead of re-creating them\n- triggers change-detection on `EmbeddedView` level\n- Zone-agnostic, opt-out of `NgZone` with `patchZone`\n- 3 Configurable `RxVirtualScrollStrategy` providing the core logic to calculate the viewRange and position DOM\n  Nodes\n  - [`FixedSizeVirtualScrollStrategy`](#fixedsizevirtualscrollstrategy)\n  - [`DynamicSizeVirtualScrollStrategy`](#dynamicsizevirtualscrollstrategy)\n  - [`AutoSizeVirtualScrollStrategy`](#autosizevirtualscrollstrategy)\n\n# Performance Benchmarks\n\nAs this library is a direct competitor of [`@angular/cdk/scrolling`](https://material.angular.io/cdk/scrolling/overview),\nthis section discusses not only performance differences, but also feature availability.\n\nPerformance recordings are taken from the [Demo Application](https://hoebbelsb.github.io/rxa-virtual-scroll/).\nThe demo application by default displays lists of `30 000` items.\n\nThe scenario that was benchmarked here is scrolling over long distances by using the scroll bar. This scenario\nputs the most pressure on the virtual scrollers.\n\n## System Setup\n\n|           |                                                            |\n| --------- | ---------------------------------------------------------- |\n| OS        | `Pop!_OS 22.04 LTS`                                        |\n| Browser   | `Chromium Version 112.0.5615.49 (Official Build) (64-bit)` |\n| Processor | `Intel® Core™ i7-9750H CPU @ 2.60GHz × 12`                 |\n\n## Different Layout techniques\n\nThe RxVirtualScrolling approach to layout items is to absolutely position every view inside the viewport. Therefore, it sets the `transform` property for each managed item.\nThe CDK approach instead transforms the viewport. The following video showcases the difference.\n\nhttps://user-images.githubusercontent.com/4904455/231340169-f65efe6c-863d-49e8-9f4f-183bb38e1b2a.mp4\n\n## Fixed Size Strategy\n\nComparison between [RxAngular FixedSizeVirtualScrollStrategy](#fixedsizevirtualscrollstrategy) and [CdkFixedSizeVirtualScroll](https://material.angular.io/cdk/scrolling/api#CdkFixedSizeVirtualScroll).\n\n[FixedSizeVirtualScrollStrategy comparison Demo](https://hoebbelsb.github.io/rxa-virtual-scroll/#/demos/fixed-size-cdk-compare)\n\n### Features\n\n| Feature           | `@rx-angular-addons/virtual-scrolling` | `@angular/cdk/scrolling` |\n| ----------------- | -------------------------------------- | ------------------------ |\n| `scrolledIndex$`  | ✅                                     | ✅                       |\n| `scrollToIndex()` | ✅                                     | ✅                       |\n\n### Performance\n\n**No throttling**\n\nBoth solutions do fine without throttling. But, the `CdkFixedSizeVirtualScroll` already struggles with the frame rate. We can already spot `partially presented frames`.\nAlso, the javascript tasks are taking longer compared to the `RxAngular FixedSizeVirtualScrollStrategy`.\n\n| `@rx-angular-addons/virtual-scrolling`                                          | `@angular/cdk/scrolling`                                                        |\n| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |\n| ![rxa-fixed-size--unthrottled](docs%2Fimages%2Frxa-fixed-size--unthrottled.png) | ![cdk-fixed-size--unthrottled](docs%2Fimages%2Fcdk-fixed-size--unthrottled.png) |\n\n**4x CPU throttling**\n\nWith throttling enabled, the `CdkFixedSizeVirtualScroll` already struggles a lot with keeping the frame rate above anything reasonable. Javascript tasks take up to ~160ms (long-tasks) and\nthe amount of `partially presented frames` increases.\nThe `RxAngular FixedSizeVirtualScrollStrategy` has no issues whatsoever keeping the frame rate above 30fps on 4x times throttling.\n\n| `@rx-angular-addons/virtual-scrolling`                                      | `@angular/cdk/scrolling`                                                    |\n| --------------------------------------------------------------------------- | --------------------------------------------------------------------------- |\n| ![rxa-fixed-size--throttled](docs%2Fimages%2Frxa-fixed-size--throttled.png) | ![cdk-fixed-size--throttled](docs%2Fimages%2Fcdk-fixed-size--throttled.png) |\n\n## Dynamic Size Strategy\n\nComparison between [RxAngular DynamicSizeVirtualScrollStrategy](#dynamicsizevirtualscrollstrategy) and [CDK AutoSizeVirtualScrollStrategy](https://github.com/angular/components/blob/main/src/cdk-experimental/scrolling/auto-size-virtual-scroll.ts).\nAs there is no real counterpart to the `DynamicSizeVirtualScrollStrategy`, the comparison was made against the `CDK AutoSizeVirtualScrollStrategy`. This is scroll behavior wise the most comparable\nimplementation from the cdk package.\n\n[DynamicSizeVirtualScrollStrategy comparison Demo](https://hoebbelsb.github.io/rxa-virtual-scroll/#/demos/dynamic-size-cdk-compare)\n\n### Features\n\nAs an experimental package, the `CDK AutoSizeVirtualScrollStrategy` does not emit the current scrollIndex, nor has it a working `scrollToIndex` method implemented.\nThe `RxAngular DynamicSizeVirtualScrollStrategy` is able to do both! It emits the current valid scrolledIndex and is able to properly scroll to the\ncorrect position based on an index.\n\n| Feature           | `@rx-angular-addons/virtual-scrolling` | `@angular/cdk/scrolling` |\n| ----------------- | -------------------------------------- | ------------------------ |\n| `scrolledIndex$`  | ✅                                     | ❌                       |\n| `scrollToIndex()` | ✅                                     | ❌                       |\n\n### Performance\n\n**No throttling**\n\nBoth solutions do fine without throttling. But, the `CDK AutoSizeVirtualScrollStrategy` struggles with the frame rate. We can already spot lots of `partially presented frames`.\nThe `RxAngular DynamicSizeVirtualScrollStrategy` implementation easily maintains a stable framerate around 45fps.\n\n| `@rx-angular-addons/virtual-scrolling`                                                  | `@angular/cdk/scrolling`                                                        |\n| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |\n| ![rxa-dynamic-size--unthrottled.png](docs%2Fimages%2Frxa-dynamic-size--unthrottled.png) | ![cdk-autosize--unthrottled.png](docs%2Fimages%2Fcdk-autosize--unthrottled.png) |\n\n**4x CPU throttling**\n\nWith throttling enabled, the `CDK AutoSizeVirtualScrollStrategy` struggles a lot with keeping the frame rate above anything reasonable. Javascript tasks take up more than ~160ms (long-tasks) and\nthe amount of `partially presented frames` increases.\nThe `RxAngular DynamicSizeVirtualScrollStrategy` has no issues whatsoever keeping the frame rate above 30fps on 4x times throttling. The javascript execution time is still very low, the style\nrecalculations and layouting phases are increasing, though. This will also depend very much on the actual use case.\n\n| `@rx-angular-addons/virtual-scrolling`                                              | `@angular/cdk/scrolling`                                                    |\n| ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |\n| ![rxa-dynamic-size--throttled.png](docs%2Fimages%2Frxa-dynamic-size--throttled.png) | ![cdk-autosize--throttled.png](docs%2Fimages%2Fcdk-autosize--throttled.png) |\n\n## Autosize Strategy\n\nComparison between [RxAngular AutosizeVirtualScrollStrategy](#autosizevirtualscrollstrategy) and [CDK AutoSizeVirtualScrollStrategy](https://github.com/angular/components/blob/main/src/cdk-experimental/scrolling/auto-size-virtual-scroll.ts).\n\n[AutosizeVirtualScrollStrategy comparison Demo](https://hoebbelsb.github.io/rxa-virtual-scroll/#/demos/autosize-cdk-compare)\n\n### Features\n\nAs an experimental package, the `CDK AutoSizeVirtualScrollStrategy` does not emit the current scrollIndex, nor has it a working `scrollToIndex` method implemented.\nThe `RxAngular AutosizeVirtualScrollStrategy` is able to do both! It emits the current valid scrolledIndex and is able to properly scroll to the\ncorrect position based on an index.\n\n| Feature           | `@rx-angular-addons/virtual-scrolling` | `@angular/cdk/scrolling` |\n| ----------------- | -------------------------------------- | ------------------------ |\n| `scrolledIndex$`  | ✅                                     | ❌                       |\n| `scrollToIndex()` | ✅                                     | ❌                       |\n\n### Performance\n\n**No throttling**\n\nFor the `CDK AutoSizeVirtualScrollStrategy`, the same is true as for the comparison vs. the `DynamicSizeVirtualScrollStrategy`.\nThe `RxAngular AutoSizeVirtualScrollStrategy` implementation easily maintains a stable framerate of 60fps. You see the reason why it can maintain this framerate in the\ncomparison flameshots. The AutoSizeVirtualScrollStrategy puts all the layouting work into the RxAngular scheduler queue which will keep the framebudget for us.\nFor each inserted view, the `AutoSizeVirtualScrollStrategy` will cause a forced reflow as it immediately reads its dimensions. It sounds like a disadvantage, but in reality\nthe scrolling performance benefits from this approach. Anyway, that's why we such heavy `rendering` peaks (purple color).\nNodes that were visited once are not queried again, scrolling the same path twice will differ in runtime performance. All consequent attempts should be as fast as the fixed or dynamic\nsize implementations.\n\n| `@rx-angular-addons/virtual-scrolling`                                          | `@angular/cdk/scrolling`                                                        |\n| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |\n| ![rxa-autosize--unthrottled.png](docs%2Fimages%2Frxa-autosize--unthrottled.png) | ![cdk-autosize--unthrottled.png](docs%2Fimages%2Fcdk-autosize--unthrottled.png) |\n\n**4x CPU throttling**\n\nFor the `CDK AutoSizeVirtualScrollStrategy`, the same is true as for the comparison vs. the `DynamicSizeVirtualScrollStrategy`.\n\nEven with 4x CPU throttling enabled, the `RxAngular AutoSizeVirtualScrollStrategy` keeps a reasonable frame rate and only sometimes produces partially presented frames.\nThanks to the concurrent strategies, users will never encounter long tasks while scrolling.\n\n| `@rx-angular-addons/virtual-scrolling`                                      | `@angular/cdk/scrolling`                                                    |\n| --------------------------------------------------------------------------- | --------------------------------------------------------------------------- |\n| ![rxa-autosize--throttled.png](docs%2Fimages%2Frxa-autosize--throttled.png) | ![cdk-autosize--throttled.png](docs%2Fimages%2Fcdk-autosize--throttled.png) |\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoebbelsb%2Frxa-virtual-scroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoebbelsb%2Frxa-virtual-scroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoebbelsb%2Frxa-virtual-scroll/lists"}