Locking Grid Header on Top While Scrolling the Page
Environment
| Product | Progress® Kendo UI for Angular Grid |
Description
I want to lock the header of the Kendo UI for Angular Grid so that it remains visible while scrolling up or down the page. Currently, the header disappears when scrolling the page vertically, which creates confusion for users trying to interpret the data.
This Knowledge Base article also answers the following questions:
- How to freeze the header of the Grid while scrolling?
- How to prevent the header from disappearing in Kendo UI for Angular Grid?
- How to make the header of the Angular Grid sticky?
Solution
To achieve this functionality, you can implement custom logic using Angular best practices with Renderer2 for DOM manipulation. This approach calculates the scroll position and toggles a custom class for the Grid header based on whether the scroll position is within the Grid's boundaries.
Follow these steps to achieve the full implementation:
-
Import the necessary Angular services and lifecycle hooks in your component.
typescriptimport { Component, Renderer2, ElementRef, AfterViewInit } from '@angular/core'; -
Inject
Renderer2andElementRefthrough the constructor and implementAfterViewInitto cache DOM elements after view initialization.typescriptexport class AppComponent implements AfterViewInit { private gridElement?: HTMLElement; private headerElement?: HTMLElement; constructor(private renderer: Renderer2, private elementRef: ElementRef) {} ngAfterViewInit(): void { // Cache DOM elements after view initialization for better performance this.gridElement = this.elementRef.nativeElement.querySelector('.k-grid'); this.headerElement = this.elementRef.nativeElement.querySelector('.k-grid-header'); } } -
Create a scroll event handler that uses the cached elements and
Renderer2for DOM manipulation.typescriptpublic onContainerScroll(event: Event): void { if (!this.gridElement || !this.headerElement) { return; } const container = event.target as HTMLElement; const scrollTop = container.scrollTop; const gridTop = this.gridElement.offsetTop; const gridBottom = gridTop + this.gridElement.clientHeight - this.headerElement.clientHeight; if (scrollTop < gridTop || scrollTop > gridBottom) { this.renderer.removeClass(this.headerElement, 'fixed-header'); this.renderer.setStyle(this.headerElement, 'width', 'auto'); } else if (scrollTop >= gridTop && scrollTop <= gridBottom) { this.renderer.addClass(this.headerElement, 'fixed-header'); this.renderer.setStyle(this.headerElement, 'width', `${this.gridElement.clientWidth}px`); } }This implementation uses
Renderer2methods for safe DOM manipulation. TheaddClassandremoveClassmethods toggle thefixed-headerCSS class based on the scroll position, whilesetStyledynamically adjusts the header width to match the Grid's width when fixed or resets it to 'auto' when not fixed. The logic ensures the header appears fixed only when the Grid content is visible within the scroll boundaries. -
Bind the scroll event handler to your scrollable container in the template.
html<div class="demo-container" (scroll)="onContainerScroll($event)"> <kendo-grid [data]="gridData"> <!-- Grid columns --> </kendo-grid> </div> -
Define suitable CSS styles that will be applied when the
fixed-headerclass is added to the Grid header.css.fixed-header { position: fixed; top: 0; z-index: 1; }
The following example demonstrates the suggested approach in action.
The demo below uses a custom scrollable container for demonstration purposes in an
iframeenvironment. In a real application, you can use thewindow:scrollevent as shown in the code snippets above.