Skip to main content

Frozen Rows and Columns

Keep the first N displayed rows in place below the header, and the first N displayed columns in place at the left, while the rest of the body scrolls, like Excel's Freeze Panes. A subtle divider marks the last frozen row; frozen columns use ordinary column pinning.

Live Demo​

Scroll down - the first two rows stay frozen under the header; scroll right - Name stays pinned. Right-click a cell to use Freeze panes.
Live

Quick Example​

import { OGrid } from '@alaarab/ogrid-react-radix';

<OGrid
columns={columns}
data={rows}
getRowId={(r) => r.id}
frozenRows={2}
frozenColumns={1}
/>;

The same props work on @alaarab/ogrid-react-fluent and on the bare DataGridTable.

Freeze commands​

Set allowFreeze to add a Freeze section to the cell context menu, like Excel's View → Freeze Panes:

  • Freeze panes — freezes the rows above and the columns left of the active cell (or the selection's top-left).
  • Freeze top row — freezes the first row.
  • Freeze first column — freezes the first column.
  • Unfreeze panes — clears both.
<OGrid
columns={columns}
data={rows}
getRowId={(r) => r.id}
allowFreeze
defaultFrozenRows={2}
onFrozenRowsChange={setFrozenRows}
/>

frozenRows / frozenColumns are controlled when passed; leave them off and the grid keeps the state itself, seeded by defaultFrozenRows / defaultFrozenColumns, and reported through onFrozenRowsChange / onFrozenColumnsChange. frozenColumns pins the first N displayed columns left, so it follows column visibility and reordering.

How It Works​

  • The frozen rows are the first frozenRows displayed rows: they follow sorting and filtering, and with pagination they are the first rows of the current page.
  • Frozen cells use position: sticky below the header. With column pinning, cells in the intersection stick on both axes.
  • With virtual scrolling, frozen rows are always rendered, however far the body is scrolled.
  • Keyboard navigation scrolls a row out from under the frozen rows when it becomes active.
  • A merged cell never spans across the frozen boundary; it is clipped there.

Styling​

The divider under the last frozen row uses --ogrid-frozen-divider (default: --ogrid-border-strong). Stacking order uses --ogrid-z-frozen (frozen cells, default 7) and --ogrid-z-frozen-pinned (frozen pinned, checkbox and row-number cells, default 9).

.my-grid {
--ogrid-frozen-divider: #217346;
}