diff --git a/libs/template/CHANGELOG.md b/libs/template/CHANGELOG.md
index 40822390b2..a7275f9f2d 100644
--- a/libs/template/CHANGELOG.md
+++ b/libs/template/CHANGELOG.md
@@ -2,6 +2,15 @@
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
+# [1.1.0](https://github.com/rx-angular/rx-angular/compare/template@1.0.0...template@1.1.0) (2023-04-13)
+
+
+### Features
+
+* **template:** introduce experimental virtual-scrolling package ([dcd98b0](https://github.com/rx-angular/rx-angular/commit/dcd98b0b9fca831e03507af2b5e71985191b4ebf))
+
+
+
# [1.0.0](https://github.com/rx-angular/rx-angular/compare/template@1.0.0-rc.5...template@1.0.0) (2023-01-29)
diff --git a/libs/template/README.md b/libs/template/README.md
index 11080a87c9..9d6ea7af9e 100644
--- a/libs/template/README.md
+++ b/libs/template/README.md
@@ -21,6 +21,7 @@
**Experimental features**
- [🧪 Viewport Priority (viewport-prio)](https://rx-angular.io/docs/template/api/experimental/viewport-prio-directive)
+- [🧪 Virtual Scrolling (`*rxVirtualFor`)](https://github.com/rx-angular/rx-angular/tree/feat-virtual-scroll/libs/template/experimental/virtual-scrolling#readme)
All experimental features are very stable and already tested in production apps for multiple months. The reason to have them in experimental is so we can make small typing changes without breaking changes.
diff --git a/libs/template/experimental/virtual-scrolling/README.md b/libs/template/experimental/virtual-scrolling/README.md
new file mode 100644
index 0000000000..3a4e5ee9f7
--- /dev/null
+++ b/libs/template/experimental/virtual-scrolling/README.md
@@ -0,0 +1,564 @@
+# RxVirtualScroll
+
+A **high performance** alternative to [`@angular/cdk/scrolling`](https://material.angular.io/cdk/scrolling/) virtual scrolling implementation.
+
+
+
+Instead of rendering every item provided, `rxVirtualFor` only renders what is currently visible to the user, thus providing
+excellent runtime performance for huge sets of data.
+
+The technique to render items is comparable to the one used by twitter and
+explained in great detail by @DasSurma in his blog post about the
+[complexities of infinite scrollers](https://developer.chrome.com/blog/infinite-scroller/).
+
+"Each recycling of a DOM element would normally relayout the entire runway which would bring us well below our target
+of 60 frames per second. To avoid this, we are taking the burden of layout onto ourselves and use absolutely positioned
+elements with transforms." (@DasSurma)
+
+# TOC
+
+- [Usage](#usage)
+- [Demo](#demo)
+- [Features](#features)
+- [Missing Features (Roadmap)](#missing-features-roadmap)
+- [Docs](#docs)
+ - [RxVirtualFor](#rxvirtualfor)
+ - [RxVirtualScrollViewportComponent](#rxvirtualfor)
+ - [RxVirtualScrollStrategy](#rxvirtualscrollstrategy)
+ - [Configuration](#configuration)
+- [Performance Benchmarks](#performance-benchmarks)
+- [Version Compatibility](#version-compatibility)
+
+## Usage
+
+```ts
+import {
+ FixedSizeVirtualScrollStrategy,
+ RxVirtualScrollingModule,
+} from '@rx-angular/template/experimental/virtual-scrolling';
+
+@NgModule({
+ imports: [RxVirtualScrollingModule, FixedSizeVirtualScrollStrategy],
+})
+export class MyModule {}
+```
+
+```html
+
+
+
+
{{ hero.name }}
+
{{ hero.id }}
+
{{ hero.description }}
+
+
+
+```
+
+## Demo
+
+Check out the [Demo Application](https://hoebbelsb.github.io/rxa-virtual-scroll/). You can play around with
+all pre-packaged ScrollStrategies as well as control the majority of inputs.
+
+## Features
+
+**DX Features**
+
+- reduces boilerplate (multiple `async` pipe's)
+- works also with static variables `*rxVirtualFor="let i of myData"`
+- Immutable as well as mutable data structures (`trackBy`)
+- Notify when rendering of templates is finished (`renderCallback`)
+
+**Performance Features**
+
+- lazy template creation (done by [Render Strategies](https://www.rx-angular.io/docs/cdk/render-strategies))
+- non-blocking rendering of lists [Concurrent Strategies](https://www.rx-angular.io/docs/cdk/render-strategies/strategies/concurrent-strategies)
+- configurable frame budget (defaults to 60 FPS)
+- Super efficient layouting with css transformations
+- Scoped layouting with css containment
+- Define a viewCache in order to re-use views instead of re-creating them
+- triggers change-detection on `EmbeddedView` level
+- Zone-agnostic, opt-out of `NgZone` with `patchZone`
+- 3 Configurable `RxVirtualScrollStrategy` providing the core logic to calculate the viewRange and position DOM
+ Nodes
+ - `FixedSizeVirtualScrollStrategy`
+ - `AutosizeVirtualScrollStrategy`
+ - `DynamicSizeVirtualScrollStrategy`
+
+## Missing Features (Roadmap)
+
+The following section describes features that are currently not implemented, but planned.
+
+### Migrate to latest angular
+
+Right now, this library is built with angular version 12 in order to have the first version being compatible with `@angular/core: >= 12`.
+It is planned to migrate to the latest angular version and adapt to new features like standalone components, provider functions and standalone components.
+
+### Support other orientations
+
+Right now, the `@rx-angular/template/experimental/virtual-scrolling` package only supports vertical scrolling. In the future, it should also
+be able to support horizontal scrolling.
+
+### Tombstones
+
+Tombstones, skeletons or placeholder templates are a nice way to improve the scrolling performance, especially when the actual views being rendered
+are heavy and take a long time to create. Especially for the autosized strategy this can increase the visual stability and runtime performance a lot.
+
+The concept is described in the article [Complexities of an infinite scroller](https://developer.chrome.com/blog/infinite-scroller/#tombstones)
+and visible in the corresponding [demo](http://googlechromelabs.github.io/ui-element-samples/infinite-scroller/).
+
+# Docs
+
+The `@rx-angular/template/experimental/virtual-scrolling` package can be seen as a high performant competitor of the
+official `@angular/cdk/scrolling`.
+The API is heavily inspired by `@angular/cdk/scrolling` and is divided into multiple
+core components which have to be glued together:
+
+- `RxVirtualViewRepeater`, implemented by `RxVirtualFor`
+- `RxVirtualScrollViewport`, implemented by `RxVirtualScrollViewportComponent`
+- `RxVirtualScrollStrategy`, implemented by `AutosizeVirtualScrollStrategy`, `FixedSizeVirtualScrollStrategy` & `DynamicSizeVirtualScrollStrategy`
+
+## API
+
+### RxVirtualFor
+
+The `*rxVirtualFor` structural directive implements the `RxVirtualViewRepeater` and is responsible to create, update, move and remove views
+from the bound data.
+As [`RxFor`](https://www.rx-angular.io/docs/template/api/rx-for-directive), `RxVirtualFor` treats each child template as single renderable unit.
+By default the change detection of the child templates get prioritized, scheduled and executed by leveraging [`RenderStrategies`](https://www.rx-angular.io/docs/cdk/render-strategies) under the hood.
+This technique enables non-blocking rendering of lists and can be referred to as concurrent mode.
+
+Read more about the concurrent mode in the [concurrent strategies section](https://www.rx-angular.io/docs/cdk/render-strategies/strategies/concurrent-strategies) in the `RxAngular` docs.
+
+#### Inputs
+
+| Input | Type | description |
+| ---------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `trackBy` | `keyof T` or `(index: number, item: T) => any` | Identifier function for items. `rxVirtualFor` provides a shorthand where you can name the property directly. |
+| `patchZone` | `boolean` | _default: `true`_ if set to `false`, the `RxVirtualForDirective` will operate out of `NgZone`. See [NgZone optimizations](https://www.rx-angular.io/docs/template/performance-issues/ngzone-optimizations) |
+| `parent` | `boolean` | _default: `false`_ if set to `false`, the `RxVirtualForDirective` won't inform its host component about changes being made to the template. More performant, `@ViewChild` and `@ContentChild` queries won't work. [Handling view and content queries](https://www.rx-angular.io/docs/template/performance-issues/handling-view-and-content-queries) |
+| `strategy` | `Observable \ RxStrategyNames \ string>` | _default: `normal`_ configure the `RxStrategyRenderStrategy` used to detect changes. [Render Strategies](https://www.rx-angular.io/docs/cdk/render-strategies) |
+| `renderCallback` | `Subject` | giving the developer the exact timing when the `RxVirtualForDirective` created, updated, removed its template. Useful for situations where you need to know when rendering is done. |
+| `viewCacheSize` | `number` | _default: `20`_ Controls the amount if views held in cache for later re-use when a user is scrolling the list If this is set to 0, `rxVirtualFor` won't cache any view, thus destroying & re-creating very often on scroll events. |
+
+#### Context Variables
+
+The following context variables are available for each template:
+
+**Static Context Variables (mirrored from `ngFor`)**
+
+| Variable Name | Type | description |
+| ------------- | --------- | ---------------------------------------------------- |
+| `$implicit` | `T` | the default variable accessed by `let val` |
+| `index` | `number` | current index of the item |
+| `count` | `number` | count of all items in the list |
+| `first` | `boolean` | true if the item is the first in the list |
+| `last` | `boolean` | true if the item is the last in the list |
+| `even` | `boolean` | true if the item has on even index (index % 2 === 0) |
+| `odd` | `boolean` | the opposite of even |
+
+**Reactive Context Variables**
+
+| Variable Name | Type | description |
+| ------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `item$` | `Observable` | the same value as $implicit, but as `Observable` |
+| `index$` | `Observable` | index as `Observable` |
+| `count$` | `Observable` | count as `Observable` |
+| `first$` | `Observable` | first as `Observable` |
+| `last$` | `Observable` | last as `Observable` |
+| `even$` | `Observable` | even as `Observable` |
+| `odd$` | `Observable` | odd as `Observable` |
+| `select` | `(keys: (keyof T)[], distinctByMap) => Observable>` | returns a selection function which accepts an array of properties to pluck out of every list item. The function returns the selected properties of the current list item as distinct `Observable` key-value-pair. |
+
+**Use the context variables**
+
+```html
+
+
+
{{ count }}
+
{{ index }}
+
{{ item }}
+
{{ first }}
+
{{ last }}
+
{{ even }}
+
{{ odd }}
+
+
+```
+
+### RxVirtualScrollViewportComponent
+
+Container component comparable to CdkVirtualScrollViewport acting as viewport for `*rxVirtualFor` to operate on.
+Its main purpose is to implement the `RxVirtualScrollViewport` interface as well as maintaining the scroll runways'
+height in order to give the provided `RxVirtualScrollStrategy` room to position items. Furthermore, it will gather and forward
+all events to the consumer of `rxVirtualFor`.
+
+#### Outputs
+
+| Output | Type | description |
+| --------------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `viewRange` | `ListRange: { start: number; end: number; }` | The range to be rendered by `*rxVirtualFor`. This value is determined by the provided `RxVirtualScrollStrategy`. It gives the user information about the range of items being actually rendered to the DOM. Note this value updates before the `renderCallback` kicks in, thus it is only in sync with the DOM when the next `renderCallback` emitted an event. |
+| `scrolledIndexChange` | `number` | The index of the currently scrolled item. The scrolled item is the topmost item actually being visible to the user. |
+
+### RxVirtualScrollStrategy
+
+The `RxVirtualScrollStrategy` is responsible for positioning the created views on the viewport.
+The three pre-packaged scroll strategies share similar concepts for layouting views.
+All of them provide a twitter-like virtual-scrolling implementation, where views are positioned absolutely and transitioned by
+using css `transforms`.
+They also share two inputs to define the amount of views to actually render on the screen.
+
+| Input | Type | description |
+| --------------------- | -------- | -------------------------------------------------------------------------------- |
+| `runwayItems` | `number` | _default: `10`_ The amount of items to render upfront in scroll direction |
+| `runwayItemsOpposite` | `number` | _default: `2`_ The amount of items to render upfront in reverse scroll direction |
+
+#### FixedSizeVirtualScrollStrategy
+
+The `FixedSizeVirtualScrollStrategy` positions views based on a fixed size per item. It is comparable to `@angular/cdk/scrolling` `FixedSizeVirtualScrollStrategy`,
+but with a high performant layouting technique.
+
+[Demo](https://hoebbelsb.github.io/rxa-virtual-scroll/#/demos/fixed-size)
+
+The default size can be configured directly as `@Input('itemSize')`.
+
+**Example**
+
+```ts
+// my.component.ts
+import {
+ FixedSizeVirtualScrollStrategyModule,
+ RxVirtualScrollingModule,
+} from '@rx-angular/template/experimental/virtual-scrolling';
+
+@Component({
+ /**/,
+ standalone: true,
+ imports: [FixedSizeVirtualScrollStrategyModule, RxVirtualScrollingModule]
+})
+export class MyComponent {
+ // all items have the height of 50px
+ itemSize = 50;
+
+ items$ = inject(DataService).getItems();
+}
+```
+
+```html
+
+
+
{{ item.id }}
+
{{ item.content }}
+
{{ item.status }}
+
{{ item.date | date }}
+
+
+```
+
+#### DynamicSizeVirtualScrollStrategy
+
+The `DynamicSizeVirtualScrollStrategy` is very similar to the `AutosizeVirtualScrollStrategy`. Instead of hitting the DOM, it calculates the size
+based on a user provided function of type `(item: T) => number`. Because it doesn't have to interact with the DOM in order to position views,
+the `DynamicSizeVirtualScrollStrategy` has a better runtime performance compared to the `AutosizeVirtualScrollStrategy`.
+
+This strategy is very useful for scenarios where you display different kind of templates, but already know the dimensions of
+them.
+
+[Demo](https://hoebbelsb.github.io/rxa-virtual-scroll/#/demos/dynamic-size)
+
+**Example**
+
+```ts
+// my.component.ts
+import {
+ DynamicSizeVirtualScrollStrategyModule,
+ RxVirtualScrollingModule,
+} from '@rx-angular/template/experimental/virtual-scrolling';
+
+@Component({
+ /**/,
+ standalone: true,
+ imports: [DynamicSizeVirtualScrollStrategyModule, RxVirtualScrollingModule]
+})
+export class MyComponent {
+ // items with a description have 120px height, others only 50px
+ dynamicSize = (item: Item) => (item.description ? 120 : 50);
+
+ items$ = inject(DataService).getItems();
+}
+```
+
+```html
+
+
+
+
{{ item.id }}
+
{{ item.content }}
+
{{ item.status }}
+
{{ item.date | date }}
+
{{ item.description }}
+
+
+```
+
+#### AutosizeVirtualScrollStrategy
+
+The `AutosizeVirtualScrollStrategy` is able to render and position
+items based on their individual size. It is comparable to `@angular/cdk/experimental` `AutosizeVirtualScrollStrategy`, but with
+a high performant layout technique, better visual stability and added features.
+Furthermore, the `AutosizeVirtualScrollStrategy` is leveraging the `ResizeObserver` in order to detect size changes for each individual
+view rendered to the DOM and properly re-position accordingly.
+
+For views it doesn't know yet, the `AutosizeVirtualScrollStrategy` anticipates a certain size in order to properly size the runway.
+The size is determined by the `@Input('tombstoneSize')` and defaults to `50`.
+
+In order to provide top runtime performance the `AutosizeVirtualScrollStrategy` builds up caches that
+prevent DOM interactions whenever possible. Once a view was visited, its properties will be stored instead of re-read from the DOM
+again as this can potentially lead to unwanted forced reflows.
+
+[Demo](https://hoebbelsb.github.io/rxa-virtual-scroll/#/demos/autosize)
+
+**Example**
+
+```ts
+// my.component.ts
+import {
+ AutosizeVirtualScrollStrategyModule,
+ RxVirtualScrollingModule,
+} from '@rx-angular/template/experimental/virtual-scrolling';
+
+@Component({
+ /**/,
+ standalone: true,
+ imports: [AutosizeVirtualScrollStrategyModule, RxVirtualScrollingModule]
+})
+export class MyComponent {
+ items$ = inject(DataService).getItems();
+}
+```
+
+```html
+
+