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(); } }