Skip to content

Commit ba35ee1

Browse files
kseamonmmalerba
authored andcommitted
perf(table): Slightly improve speed of adding/remvoing sticky styles (#19823)
* perf(table): Slightly improve speed of adding/remvoing sticky styles * fix scss * Fix * tests fixed * approve api * comments * build * lint (cherry picked from commit 1b1c31e)
1 parent c60fc9e commit ba35ee1

File tree

11 files changed

+56
-8
lines changed

11 files changed

+56
-8
lines changed

src/cdk/table/sticky-styler.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type StickyDirection = 'top' | 'bottom' | 'left' | 'right';
2121
*/
2222
export const STICKY_DIRECTIONS: StickyDirection[] = ['top', 'bottom', 'left', 'right'];
2323

24+
2425
/**
2526
* Applies and removes sticky positioning styles to the `CdkTable` rows and columns cells.
2627
* @docs-private
@@ -34,12 +35,16 @@ export class StickyStyler {
3435
* @param direction The directionality context of the table (ltr/rtl); affects column positioning
3536
* by reversing left/right positions.
3637
* @param _isBrowser Whether the table is currently being rendered on the server or the client.
38+
* @param _needsPositionStickyOnElement Whether we need to specify position: sticky on cells
39+
* using inline styles. If false, it is assumed that position: sticky is included in
40+
* the component stylesheet for _stickCellCss.
3741
*/
3842
constructor(private _isNativeHtmlTable: boolean,
3943
private _stickCellCss: string,
4044
public direction: Direction,
4145
private _coalescedStyleScheduler: _CoalescedStyleScheduler,
42-
private _isBrowser = true) { }
46+
private _isBrowser = true,
47+
private readonly _needsPositionStickyOnElement = true) { }
4348

4449
/**
4550
* Clears the sticky positioning styles from the row and its cells by resetting the `position`
@@ -204,13 +209,21 @@ export class StickyStyler {
204209
for (const dir of stickyDirections) {
205210
element.style[dir] = '';
206211
}
207-
element.style.zIndex = this._getCalculatedZIndex(element);
208212

209213
// If the element no longer has any more sticky directions, remove sticky positioning and
210214
// the sticky CSS class.
211-
const hasDirection = STICKY_DIRECTIONS.some(dir => !!element.style[dir]);
212-
if (!hasDirection) {
213-
element.style.position = '';
215+
// Short-circuit checking element.style[dir] for stickyDirections as they
216+
// were already removed above.
217+
const hasDirection = STICKY_DIRECTIONS.some(dir =>
218+
stickyDirections.indexOf(dir) === -1 && element.style[dir]);
219+
if (hasDirection) {
220+
element.style.zIndex = this._getCalculatedZIndex(element);
221+
} else {
222+
// When not hasDirection, _getCalculatedZIndex will always return ''.
223+
element.style.zIndex = '';
224+
if (this._needsPositionStickyOnElement) {
225+
element.style.position = '';
226+
}
214227
element.classList.remove(this._stickCellCss);
215228
}
216229
}
@@ -223,8 +236,10 @@ export class StickyStyler {
223236
_addStickyStyle(element: HTMLElement, dir: StickyDirection, dirValue: number) {
224237
element.classList.add(this._stickCellCss);
225238
element.style[dir] = `${dirValue}px`;
226-
element.style.cssText += 'position: -webkit-sticky; position: sticky; ';
227239
element.style.zIndex = this._getCalculatedZIndex(element);
240+
if (this._needsPositionStickyOnElement) {
241+
element.style.cssText += 'position: -webkit-sticky; position: sticky; ';
242+
}
228243
}
229244

230245
/**

src/cdk/table/table.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ export class CdkTable<T> implements AfterContentChecked, CollectionViewer, OnDes
310310
*/
311311
protected stickyCssClass: string = 'cdk-table-sticky';
312312

313+
/**
314+
* Whether to manually add positon: sticky to all sticky cell elements. Not needed if
315+
* the position is set in a selector associated with the value of stickyCssClass. May be
316+
* overridden by table subclasses
317+
*/
318+
protected needsPositionStickyOnElement = true;
319+
313320
/** Whether the no data row is currently showing anything. */
314321
private _isShowingNoDataRow = false;
315322

@@ -1096,7 +1103,7 @@ export class CdkTable<T> implements AfterContentChecked, CollectionViewer, OnDes
10961103
const direction: Direction = this._dir ? this._dir.value : 'ltr';
10971104
this._stickyStyler = new StickyStyler(
10981105
this._isNativeHtmlTable, this.stickyCssClass, direction, this._coalescedStyleScheduler,
1099-
this._platform.isBrowser);
1106+
this._platform.isBrowser, this.needsPositionStickyOnElement);
11001107
(this._dir ? this._dir.change : observableOf<Direction>())
11011108
.pipe(takeUntil(this._onDestroy))
11021109
.subscribe(value => {

src/material-experimental/mdc-table/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ sass_binary(
4444
deps = [
4545
"//src/material-experimental/mdc-helpers:mdc_helpers_scss_lib",
4646
"//src/material-experimental/mdc-helpers:mdc_scss_deps_lib",
47+
"//src/material/core:core_scss_lib",
4748
],
4849
)
4950

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
@use '../../material/core/style/vendor-prefixes';
12
@import '@material/data-table/mixins.import';
23
@import '../mdc-helpers/mdc-helpers';
34

45
@include mdc-data-table-core-styles($query: $mat-base-styles-without-animation-query);
6+
7+
.mat-table-sticky {
8+
@include vendor-prefixes.position-sticky;
9+
}

src/material-experimental/mdc-table/table.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ export class MatTable<T> extends CdkTable<T> implements OnInit {
3030
/** Overrides the sticky CSS class set by the `CdkTable`. */
3131
protected stickyCssClass = 'mat-mdc-table-sticky';
3232

33+
/** Overrides the need to add position: sticky on every sticky cell element in `CdkTable`. */
34+
protected needsPositionStickyOnElement = false;
35+
3336
// After ngOnInit, the `CdkTable` has created and inserted the table sections (thead, tbody,
3437
// tfoot). MDC requires the `mdc-data-table__content` class to be added to the body.
3538
ngOnInit() {

src/material/core/style/_vendor-prefixes.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,9 @@
3838
-webkit-backface-visibility: $value;
3939
backface-visibility: $value;
4040
}
41+
42+
@mixin position-sticky {
43+
position: -webkit-sticky;
44+
position: sticky;
45+
}
4146
/* stylelint-enable */

src/material/table/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ sass_library(
3838
sass_binary(
3939
name = "table_scss",
4040
src = "table.scss",
41+
deps = ["//src/material/core:core_scss_lib"],
4142
)
4243

4344
ng_test_library(

src/material/table/table.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@use '../core/style/vendor-prefixes';
2+
13
$mat-header-row-height: 56px;
24
$mat-row-height: 48px;
35
$mat-row-horizontal-padding: 24px;
@@ -114,3 +116,7 @@ th.mat-header-cell:last-of-type, td.mat-cell:last-of-type, td.mat-footer-cell:la
114116
padding-left: $mat-row-horizontal-padding;
115117
}
116118
}
119+
120+
.mat-table-sticky {
121+
@include vendor-prefixes.position-sticky;
122+
}

src/material/table/table.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,7 @@ import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/co
3838
export class MatTable<T> extends CdkTable<T> {
3939
/** Overrides the sticky CSS class set by the `CdkTable`. */
4040
protected stickyCssClass = 'mat-table-sticky';
41+
42+
/** Overrides the need to add position: sticky on every sticky cell element in `CdkTable`. */
43+
protected needsPositionStickyOnElement = false;
4144
}

tools/public_api_guard/cdk/table.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ export declare class CdkTable<T> implements AfterContentChecked, CollectionViewe
204204
set dataSource(dataSource: CdkTableDataSourceInput<T>);
205205
get multiTemplateDataRows(): boolean;
206206
set multiTemplateDataRows(v: boolean);
207+
protected needsPositionStickyOnElement: boolean;
207208
protected stickyCssClass: string;
208209
get trackBy(): TrackByFunction<T>;
209210
set trackBy(fn: TrackByFunction<T>);
@@ -316,7 +317,7 @@ export declare type StickyDirection = 'top' | 'bottom' | 'left' | 'right';
316317

317318
export declare class StickyStyler {
318319
direction: Direction;
319-
constructor(_isNativeHtmlTable: boolean, _stickCellCss: string, direction: Direction, _coalescedStyleScheduler: _CoalescedStyleScheduler, _isBrowser?: boolean);
320+
constructor(_isNativeHtmlTable: boolean, _stickCellCss: string, direction: Direction, _coalescedStyleScheduler: _CoalescedStyleScheduler, _isBrowser?: boolean, _needsPositionStickyOnElement?: boolean);
320321
_addStickyStyle(element: HTMLElement, dir: StickyDirection, dirValue: number): void;
321322
_getCalculatedZIndex(element: HTMLElement): string;
322323
_getCellWidths(row: HTMLElement): number[];

tools/public_api_guard/material/table.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export declare class MatRowDef<T> extends CdkRowDef<T> {
7474
}
7575

7676
export declare class MatTable<T> extends CdkTable<T> {
77+
protected needsPositionStickyOnElement: boolean;
7778
protected stickyCssClass: string;
7879
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatTable<any>, "mat-table, table[mat-table]", ["matTable"], {}, {}, never, ["caption", "colgroup, col"]>;
7980
static ɵfac: i0.ɵɵFactoryDef<MatTable<any>, never>;

0 commit comments

Comments
 (0)