---
{
  title: 'Data Grid Performance',
  description: 'Performance characteristics of NVIDIA Elements Data Grid: virtual scrolling, render budgets, and large-dataset patterns.',
  layout: 'docs.11ty.js',
  tag: 'nve-grid',
  associatedElements: ['nve-grid-header', 'nve-grid-column', 'nve-grid-row', 'nve-grid-cell'],
  hideStatus: true
}
---

## Approach

The grid leverages two approaches to maximize render performance including [CSS Contain](https://developer.mozilla.org/en-US/docs/Web/CSS/contain) and [Element Internal States](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states) Performance depends on the elements rendered within the grid itself. Average performance of 1000 rows and 4000 cells is around 250–300 ms in a typical application. Extra elements within cells add to the total render time. Use pagination or batch rendering to improve total initial render performance.

## Best Practices

{% example '@nvidia-elements/core/grid/grid.examples.json' 'Performance' '{ "inline": false, "height": "520px" }' %}

## Infinite Scroll

Batch rendering allows you to dynamically add rows for improved performance. The grid dispatches a `scrollboxend` event when the user has scrolled to the end of the current scroll box. When the event occurs you can append more rows.

<!-- todo {% example '@nvidia-elements/core/grid/grid.examples.json' 'PerformanceInfiniteScroll' %} -->

### Lit Example {% svg-logo 'lit' '20' %}

```typescript
@customElement('batch-render-demo')
class BatchRenderDemo extends LitElement {
  @state() rows = [];

  render() {
    return html`
      <nve-grid style="--scroll-height: 400px" @scrollboxend=${() => this.#loadNextGroup()}>
        ...
        ${this.rows.map(row => html`<nve-grid-row>...</nve-grid-row>`)}
      </nve-grid>
    `
  }

  connectedCallback() {
    super.connectedCallback();
    this.#loadNextGroup();
  }

  #loadNextGroup() {
    this.rows = [...this.rows, ...getNextBatch()];
  }
}
```

## Virtual Scroll

You can add Virtual Scroll using a virtual scroll package such as [@lit-labs/virtualizer](https://www.npmjs.com/package/@lit-labs/virtualizer) or [@angular/cdk](https://material.angular.io/cdk/scrolling/overview). When using a virtual scroll container apply the `scroller` attribute for the grid to know the assigned scrolling container.

<nve-alert status="warning">
  Warning: using advanced features may be unavailable such as keyboard navigation shortcuts. Be aware of <a nve-text="link" href="https://adrianroselli.com/2014/05/so-you-think-you-built-good-infinite.html">accessibility risks</a>.
</nve-alert>

<!-- todo {% example '@nvidia-elements/core/grid/grid.examples.json' 'PerformanceVirtualScroll' %} -->

### Lit Example {% svg-logo 'lit' '18' %}

```typescript
@customElement('grid-virtual-scroll-demo')
class GridVirtualScrollDemo extends LitElement {
  items = new Array(10000).fill('').map((_i, n) => ({ column: `${n}-0`, column1: `${n}-1`, column2: `${n}-2`, column3: `${n}-3` }));

  render() {
    return html`
      <nve-grid>
        <nve-grid-header>
          <nve-grid-column>column</nve-grid-column>
          <nve-grid-column>column</nve-grid-column>
          <nve-grid-column>column</nve-grid-column>
          <nve-grid-column>column</nve-grid-column>
        </nve-grid-header>

        <lit-virtualizer style="min-height: 300px" scroller .items=${this.items} .renderItem=${i => html`
          <nve-grid-row style="width: 100%">
            ${Object.keys(i).map(key => html`<nve-grid-cell>${i[key]}</nve-grid-cell>`)}
          </nve-grid-row>`}>
        </lit-virtualizer>
      </nve-grid>
    `;
  }
}
```
