Skip to content

Commit 4a9fe87

Browse files
mmalerbajelbourn
authored andcommitted
perf(virtual-scroll): improve scrolling performance (#12490)
Adds contain and translateZ to viewport and wrapper CSS and switches spacer to use transform instead of width/height
1 parent 674ebcd commit 4a9fe87

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

src/cdk/scrolling/virtual-scroll-viewport.html

+1-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,4 @@
99
Spacer used to force the scrolling container to the correct size for the *total* number of items
1010
so that the scrollbar captures the size of the entire data set.
1111
-->
12-
<div class="cdk-virtual-scroll-spacer"
13-
[style.height.px]="orientation === 'horizontal' ? 1 : _totalContentSize"
14-
[style.width.px]="orientation === 'horizontal' ? _totalContentSize : 1">
15-
</div>
12+
<div class="cdk-virtual-scroll-spacer" [style.transform]="_totalContentSizeTransform"></div>

src/cdk/scrolling/virtual-scroll-viewport.scss

+18-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ cdk-virtual-scroll-viewport {
3232
display: block;
3333
position: relative;
3434
overflow: auto;
35+
contain: strict;
36+
transform: translateZ(0);
37+
will-change: scroll-position;
3538
}
3639

3740
// Wrapper element for the rendered content. This element will be transformed to push the rendered
@@ -40,7 +43,8 @@ cdk-virtual-scroll-viewport {
4043
position: absolute;
4144
top: 0;
4245
left: 0;
43-
will-change: contents, transform;
46+
contain: content;
47+
will-change: transform;
4448
}
4549

4650
.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper {
@@ -57,5 +61,17 @@ cdk-virtual-scroll-viewport {
5761
// set if it were rendered all at once. This ensures that the scrollable content region is the
5862
// correct size.
5963
.cdk-virtual-scroll-spacer {
60-
will-change: height, width;
64+
position: absolute;
65+
top: 0;
66+
left: 0;
67+
height: 1px;
68+
width: 1px;
69+
transform-origin: 0 0;
70+
will-change: transform;
71+
72+
[dir='rtl'] & {
73+
right: 0;
74+
left: auto;
75+
transform-origin: 100% 0;
76+
}
6177
}

src/cdk/scrolling/virtual-scroll-viewport.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,16 @@ export class CdkVirtualScrollViewport implements OnInit, OnDestroy {
7777
/** A stream that emits whenever the rendered range changes. */
7878
renderedRangeStream: Observable<ListRange> = this._renderedRangeSubject.asObservable();
7979

80+
/**
81+
* The transform used to scale the spacer to the same size as all content, including content that
82+
* is not currently rendered.
83+
*/
84+
_totalContentSizeTransform = '';
85+
8086
/**
8187
* The total size of all content (in pixels), including content that is not currently rendered.
8288
*/
83-
_totalContentSize = 0;
89+
private _totalContentSize = 0;
8490

8591
/**
8692
* 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 {
211217
setTotalContentSize(size: number) {
212218
if (this._totalContentSize !== size) {
213219
this._totalContentSize = size;
220+
const axis = this.orientation == 'horizontal' ? 'X' : 'Y';
221+
this._totalContentSizeTransform = `scale${axis}(${this._totalContentSize})`;
214222
this._markChangeDetectionNeeded();
215223
}
216224
}

0 commit comments

Comments
 (0)