Skip to content

Frozen Rows & Columns

WitTable supports freezing rows and columns via FrozenPaneManager. Frozen rows stay pinned at the top and frozen columns stay pinned on the left as the user scrolls. The renderer splits the viewport into four independent regions: corner (frozen rows + frozen cols), frozen-row strip, frozen-col strip, and main scrollable content.

Merged regions cannot span across frozen boundaries — a merge must be entirely within frozen or unfrozen space.

import { WitTable } from '@witqq/spreadsheet-react';
function App() {
return (
<WitTable
columns={columns}
data={data}
frozenRows={1}
frozenColumns={2}
/>
);
}

The first row and first two columns remain visible while the rest of the grid scrolls.

Live Demo
Scroll to see row 1 and first 2 columns stay frozen in place.
View source code
FrozenPanesDemo.tsx
import { WitTable } from '@witqq/spreadsheet-react';
import { DemoWrapper } from './DemoWrapper';
import { generateEmployees, employeeColumns } from './generate-data';
import { useSiteTheme } from './useSiteTheme';
const data = generateEmployees(100);
export function FrozenPanesDemo() {
const { witTheme } = useSiteTheme();
return (
<DemoWrapper title="Live Demo" description="Scroll to see row 1 and first 2 columns stay frozen in place." height={440}>
<WitTable
theme={witTheme}
columns={employeeColumns}
data={data}
frozenRows={1}
frozenColumns={2}
showRowNumbers
style={{ width: '100%', height: '100%' }}
/>
</DemoWrapper>
);
}

A common pattern is freezing just the header row so column labels remain visible when scrolling through large datasets:

function LargeDataTable({ data }: { data: Row[] }) {
const columns: ColumnDef[] = [
{ key: 'id', title: 'ID', width: 60 },
{ key: 'name', title: 'Name', width: 200 },
{ key: 'department', title: 'Department', width: 150 },
{ key: 'salary', title: 'Salary', type: 'number', width: 120 },
];
return (
<WitTable
columns={columns}
data={data}
frozenRows={1}
frozenColumns={0}
/>
);
}

When both rows and columns are frozen, the canvas renders four independent regions:

RegionPositionContent
CornerTop-leftIntersection of frozen rows and frozen cols
Frozen-rowTop-rightFrozen rows in scrollable columns
Frozen-colBottom-leftFrozen columns in scrollable rows
MainBottom-rightScrollable content

Each region is clipped independently and the frozen regions use cached ImageData for performance — they only re-render when their content changes, not on every scroll frame.