diff --git a/src/cdk/scrolling/virtual-scroll-viewport.html b/src/cdk/scrolling/virtual-scroll-viewport.html
index e545f0ff4dd..4da0d8085b5 100644
--- a/src/cdk/scrolling/virtual-scroll-viewport.html
+++ b/src/cdk/scrolling/virtual-scroll-viewport.html
@@ -9,7 +9,4 @@
Spacer used to force the scrolling container to the correct size for the *total* number of items
so that the scrollbar captures the size of the entire data set.
-->
-
-
+
diff --git a/src/cdk/scrolling/virtual-scroll-viewport.scss b/src/cdk/scrolling/virtual-scroll-viewport.scss
index 9b7c5f0377e..2cf62ff100e 100644
--- a/src/cdk/scrolling/virtual-scroll-viewport.scss
+++ b/src/cdk/scrolling/virtual-scroll-viewport.scss
@@ -32,6 +32,9 @@ cdk-virtual-scroll-viewport {
display: block;
position: relative;
overflow: auto;
+ contain: strict;
+ transform: translateZ(0);
+ will-change: scroll-position;
}
// Wrapper element for the rendered content. This element will be transformed to push the rendered
@@ -40,7 +43,8 @@ cdk-virtual-scroll-viewport {
position: absolute;
top: 0;
left: 0;
- will-change: contents, transform;
+ contain: content;
+ will-change: transform;
}
.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper {
@@ -57,5 +61,17 @@ cdk-virtual-scroll-viewport {
// set if it were rendered all at once. This ensures that the scrollable content region is the
// correct size.
.cdk-virtual-scroll-spacer {
- will-change: height, width;
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 1px;
+ width: 1px;
+ transform-origin: 0 0;
+ will-change: transform;
+
+ [dir='rtl'] & {
+ right: 0;
+ left: auto;
+ transform-origin: 100% 0;
+ }
}
diff --git a/src/cdk/scrolling/virtual-scroll-viewport.ts b/src/cdk/scrolling/virtual-scroll-viewport.ts
index 2b81861a95a..530831e4bbe 100644
--- a/src/cdk/scrolling/virtual-scroll-viewport.ts
+++ b/src/cdk/scrolling/virtual-scroll-viewport.ts
@@ -77,10 +77,16 @@ export class CdkVirtualScrollViewport implements OnInit, OnDestroy {
/** A stream that emits whenever the rendered range changes. */
renderedRangeStream: Observable = this._renderedRangeSubject.asObservable();
+ /**
+ * The transform used to scale the spacer to the same size as all content, including content that
+ * is not currently rendered.
+ */
+ _totalContentSizeTransform = '';
+
/**
* The total size of all content (in pixels), including content that is not currently rendered.
*/
- _totalContentSize = 0;
+ private _totalContentSize = 0;
/**
* The CSS transform applied to the rendered subset of items so that they appear within the bounds
@@ -211,6 +217,8 @@ export class CdkVirtualScrollViewport implements OnInit, OnDestroy {
setTotalContentSize(size: number) {
if (this._totalContentSize !== size) {
this._totalContentSize = size;
+ const axis = this.orientation == 'horizontal' ? 'X' : 'Y';
+ this._totalContentSizeTransform = `scale${axis}(${this._totalContentSize})`;
this._markChangeDetectionNeeded();
}
}