Skip to content

Commit

Permalink
perf(virtual-scroll): improve scrolling performance (#12490)
Browse files Browse the repository at this point in the history
Adds contain and translateZ to viewport and wrapper CSS and switches spacer to use transform instead of width/height
  • Loading branch information
mmalerba authored and jelbourn committed Aug 3, 2018
1 parent 674ebcd commit 4a9fe87
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
5 changes: 1 addition & 4 deletions src/cdk/scrolling/virtual-scroll-viewport.html
Original file line number Diff line number Diff line change
Expand Up @@ -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.
-->
<div class="cdk-virtual-scroll-spacer"
[style.height.px]="orientation === 'horizontal' ? 1 : _totalContentSize"
[style.width.px]="orientation === 'horizontal' ? _totalContentSize : 1">
</div>
<div class="cdk-virtual-scroll-spacer" [style.transform]="_totalContentSizeTransform"></div>
20 changes: 18 additions & 2 deletions src/cdk/scrolling/virtual-scroll-viewport.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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;
}
}
10 changes: 9 additions & 1 deletion src/cdk/scrolling/virtual-scroll-viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,16 @@ export class CdkVirtualScrollViewport implements OnInit, OnDestroy {
/** A stream that emits whenever the rendered range changes. */
renderedRangeStream: Observable<ListRange> = 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
Expand Down Expand Up @@ -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();
}
}
Expand Down

0 comments on commit 4a9fe87

Please sign in to comment.