Resizable columns
Enable drag-to-resize handles on column headers by setting resizable.
Users drag the right edge of any header cell to adjust its width, by mouse or touch.
Resize is fully compatible with sorting, pagination, filtering, pinning, and column reordering.
Resizable columns
Drag the right edge of any column header to resize it.
import DataTable, { type TableColumn } from 'react-data-table-component';
const columns: TableColumn<Employee>[] = [
{ name: 'Name', selector: r => r.name, width: '180px', minWidth: '100px' },
{ name: 'Role', selector: r => r.role, minWidth: '120px' },
{ name: 'Department', selector: r => r.department, width: '140px', minWidth: '80px' },
{
name: 'Salary',
selector: r => r.salary,
width: '110px',
right: true,
format: r => `$${r.salary.toLocaleString()}`,
},
];
<DataTable columns={columns} data={data} resizable highlightOnHover />;
How it works
The resize handle sits straddling the right edge of each header cell, a 6 px hit area
centered on the column boundary so it aligns with the column separator. On
mousedown, a global mousemove listener tracks the delta and
writes the new width to component state; the affected column receives an inline
width style. Only the resized column re-renders.
Initial and minimum widths
width sets the starting width; minWidth clamps how small a
user can drag the column. Columns without a fixed width start at their
natural flex width and remain resizable.
const columns: TableColumn<Employee>[] = [
{ name: 'Name', selector: r => r.name, width: '200px', minWidth: '120px' },
{ name: 'Status', selector: r => r.status, width: '100px' },
{ name: 'Notes', selector: r => r.notes /* grows to fill remaining space */ },
];
<DataTable columns={columns} data={data} resizable />;
The hard floor is 40 px. DataTable won't allow narrower than that regardless of minWidth.
Visual indicator
The handle is invisible until hover. On hover or active drag, a 2 px center line
appears in your primary color (--rdt-color-primary). The line sits exactly
on the column boundary so it visually replaces the separator while resizing.
Persisting widths
Pass onColumnResize to receive the settled width after every drag, and
initialColumnWidths to hydrate saved widths on mount. Both are keyed by
the id you set on each column:
import { useState } from 'react';
import DataTable, { type TableColumn } from 'react-data-table-component';
const STORAGE_KEY = 'employees-table-widths';
function loadWidths(): Record<string, number> {
try {
return JSON.parse(localStorage.getItem(STORAGE_KEY) ?? '{}');
} catch {
return {};
}
}
export default function App() {
const [initialWidths] = useState(loadWidths);
const columns: TableColumn<Employee>[] = [
{ id: 'name', name: 'Name', selector: r => r.name },
{ id: 'salary', name: 'Salary', selector: r => r.salary, right: true },
];
return (
<DataTable
columns={columns}
data={data}
resizable
initialColumnWidths={initialWidths}
onColumnResize={(_id, _width, allWidths) =>
localStorage.setItem(STORAGE_KEY, JSON.stringify(allWidths))
}
/>
);
}
See the Persist column widths recipe for a live demo, including saving to a back-end API instead of localStorage.
| Prop | Type | Description |
|---|---|---|
initialColumnWidths | Record<string | number, number> | Seed column widths (px) by column id on mount. |
onColumnResize | (columnId, width, allWidths) => void | Called with the column id, final width (px), and full widths map after a resize. |
With column pinning
Resize works on pinned columns. When a pinned column's width changes, the sticky offsets for columns pinned further from the edge update automatically. The pin band shifts to stay aligned.
Resetting widths
Force a remount of DataTable to clear all resize state. The simplest approach is a
React key bump:
const [resetKey, setResetKey] = useState(0);
<button onClick={() => {
localStorage.removeItem(STORAGE_KEY);
setResetKey(k => k + 1);
}}>Reset column widths</button>
<DataTable key={resetKey} columns={columns} data={data} resizable />
Accessibility
The resize handle is pointer-only (mouse and touch). Keyboard users cannot drag-resize. If keyboard-accessible resizing matters for your audience, provide a settings UI (a popover with width inputs per column) as an alternative.
Prop reference
| Prop | Type | Default | Description |
|---|---|---|---|
resizable | boolean | false | Show drag handles on column headers for resizing. |
initialColumnWidths | Record<string | number, number> | - | Seed column widths (px) by column id on mount. |
onColumnResize | (columnId, width, allWidths) => void | - | Called with the column id, final width (px), and full widths map after a resize. |
| Column prop | Type | Description |
|---|---|---|
width | string | Fixed column width, e.g. "120px". With resizable, this is the starting width. |
minWidth | string | Minimum width. Defaults to "100px" when neither width nor minWidth is set. With resizable, the user cannot drag narrower than this, with a hard floor of 40px. |