Column groups
Group your columns, using multiple levels of nested column headers, to better reflect the structure of your data.
Nested column headers
The NestedHeaders plugin allows you to create a nested headers structure by using the HTML colspan and rowspan attributes.
To create a header that spans multiple columns, its corresponding configuration array element should be provided as an object with label and colspan
properties. The label property defines the header’s label, while the colspan property defines the number of columns that the header should cover.
To create a header that spans multiple header rows, add a rowspan property to that object. See Rowspan below.
Configuration
nestedHeaders={[ ['A', { label: 'B', colspan: 8 }, 'C'], ['D', { label: 'E', colspan: 4 }, { label: 'F', colspan: 4 }, 'G'], ['H', { label: 'I', colspan: 2 }, { label: 'J', colspan: 2 }, { label: 'K', colspan: 2 }, { label: 'L', colspan: 2 }, 'M'], ['N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W']]}Example
import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { return ( <HotTable data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4', 'J4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5', 'J5'], ]} colHeaders={true} rowHeaders={true} height="auto" nestedHeaders={[ ['A', { label: 'B', colspan: 8 }, 'C'], ['D', { label: 'E', colspan: 4 }, { label: 'F', colspan: 4 }, 'G'], [ 'H', { label: 'I', colspan: 2 }, { label: 'J', colspan: 2 }, { label: 'K', colspan: 2 }, { label: 'L', colspan: 2 }, 'M', ], ['N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'], ]} autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> );};
export default ExampleComponent;import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { return ( <HotTable data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4', 'J4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5', 'J5'], ]} colHeaders={true} rowHeaders={true} height="auto" nestedHeaders={[ ['A', { label: 'B', colspan: 8 }, 'C'], ['D', { label: 'E', colspan: 4 }, { label: 'F', colspan: 4 }, 'G'], [ 'H', { label: 'I', colspan: 2 }, { label: 'J', colspan: 2 }, { label: 'K', colspan: 2 }, { label: 'L', colspan: 2 }, 'M', ], ['N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'], ]} autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> );};
export default ExampleComponent;Rowspan
The rowspan property sets how many header rows a single header cell should cover. Use an integer greater than 1. Positions in lower rows that sit under that cell can use an empty string '' as a placeholder, but those placeholders are optional. Handsontable can infer covered slots when you omit them.
You can combine rowspan and colspan on the same header object. The same rules apply as for colspan only: a header cannot be wider than its parent in the hierarchy, and overlapping header definitions are not supported.
Configuration
nestedHeaders={[ [{ label: 'A', rowspan: 2 }, { label: 'B', colspan: 2 }], ['', 'C', 'D'],]}Collapsible headers
The CollapsibleColumns plugin enables columns and their headers to be collapsed/expanded.
This plugin adds multi-column headers which have buttons. Clicking these buttons will collapse or expand all “child” headers, leaving the first one visible.
The NestedHeaders plugin needs to be enabled for this to work properly.
Configuration
To enable the Collapsible Columns plugin, either set the collapsibleColumns configuration option to:
true- this will enable the functionality for all multi-column headers, every column with thecolspanattribute defined will be extended with the “expand/collapse” button- An array of objects containing information specifying which headers should have the “expand/collapse” buttons for example:
collapsibleColumns={[ { row: -4, col: 1, collapsible: true }, // Add the button to the 4th-level header of the 1st column - counting from the first table row upwards. { row: -3, col: 5, collapsible: true } // Add the button to the 3rd-level header of the 5th column - counting from the first table row upwards.]}Example
import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { return ( <HotTable data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4', 'J4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5', 'J5'], ]} colHeaders={true} rowHeaders={true} colWidths={60} height="auto" nestedHeaders={[ ['A', { label: 'B', colspan: 8 }, 'C'], ['D', { label: 'E', colspan: 4 }, { label: 'F', colspan: 4 }, 'G'], [ 'H', { label: 'I', colspan: 2 }, { label: 'J', colspan: 2 }, { label: 'K', colspan: 2 }, { label: 'L', colspan: 2 }, 'M', ], ['N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'], ]} collapsibleColumns={[ { row: -4, col: 1, collapsible: true }, { row: -3, col: 1, collapsible: true }, { row: -2, col: 1, collapsible: true }, { row: -2, col: 3, collapsible: true }, ]} autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> );};
export default ExampleComponent;import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { return ( <HotTable data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4', 'J4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5', 'J5'], ]} colHeaders={true} rowHeaders={true} colWidths={60} height="auto" nestedHeaders={[ ['A', { label: 'B', colspan: 8 }, 'C'], ['D', { label: 'E', colspan: 4 }, { label: 'F', colspan: 4 }, 'G'], [ 'H', { label: 'I', colspan: 2 }, { label: 'J', colspan: 2 }, { label: 'K', colspan: 2 }, { label: 'L', colspan: 2 }, 'M', ], ['N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'], ]} collapsibleColumns={[ { row: -4, col: 1, collapsible: true }, { row: -3, col: 1, collapsible: true }, { row: -2, col: 1, collapsible: true }, { row: -2, col: 3, collapsible: true }, ]} autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> );};
export default ExampleComponent;Choose which columns stay visible when collapsed
By default, collapsing a group leaves its first column visible. To choose which columns stay visible in each state, add the visibleWhen property to a header in the nestedHeaders configuration. It accepts three values:
'collapsed'- the column is visible only while its group is collapsed (hidden while expanded).'expanded'- the column is visible only while its group is expanded (hidden while collapsed).'always'- the column is visible in both states.
Once a group uses visibleWhen on any of its headers, the headers you leave unmarked default to 'expanded' - they are hidden when the group collapses. So you only mark the column(s) you want to keep: tag one with 'always' (stays in both states) or 'collapsed' (a summary column that appears only on collapse). At least one column of a group always stays visible, so its collapse button is never lost.
In the example below, collapse the Q1 2025 group: the per-month columns (marked 'expanded') hide and the Total column ('collapsed') appears. Expanding the group reverses it.
import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { return ( <HotTable data={[ ['North America', 4200, 3800, 4500, 12500], ['Europe', 3100, 2900, 3300, 9300], ['Asia Pacific', 2600, 2400, 2800, 7800], ['Latin America', 1500, 1700, 1600, 4800], ['Middle East', 1200, 1300, 1450, 3950], ]} colHeaders={true} rowHeaders={true} colWidths={90} height="auto" nestedHeaders={[ ['Region', { label: 'Q1 2025', colspan: 4 }], [ 'Region', { label: 'Jan', visibleWhen: 'expanded' }, { label: 'Feb', visibleWhen: 'expanded' }, { label: 'Mar', visibleWhen: 'expanded' }, { label: 'Total', visibleWhen: 'collapsed' }, ], ]} collapsibleColumns={true} autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> );};
export default ExampleComponent;import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { return ( <HotTable data={[ ['North America', 4200, 3800, 4500, 12500], ['Europe', 3100, 2900, 3300, 9300], ['Asia Pacific', 2600, 2400, 2800, 7800], ['Latin America', 1500, 1700, 1600, 4800], ['Middle East', 1200, 1300, 1450, 3950], ]} colHeaders={true} rowHeaders={true} colWidths={90} height="auto" nestedHeaders={[ ['Region', { label: 'Q1 2025', colspan: 4 }], [ 'Region', { label: 'Jan', visibleWhen: 'expanded' }, { label: 'Feb', visibleWhen: 'expanded' }, { label: 'Mar', visibleWhen: 'expanded' }, { label: 'Total', visibleWhen: 'collapsed' }, ], ]} collapsibleColumns={true} autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> );};
export default ExampleComponent;A group whose headers use no visibleWhen markers keeps the default behavior - collapsing leaves its first column visible. The visibleWhen property applies only to headers within a collapsible group.
Known limitations
- A column header can span up to 1000 columns, as the HTML table specification sets the
limit of
colspanto1000. - A nested column header can’t be wider than its parent element (headers can’t overlap).
- If
rowspanis larger than the number of header rows below the cell, Handsontable clamps it to the remaining header levels.
Related keyboard shortcuts
| Windows | macOS | Action | Excel | Sheets |
|---|---|---|---|---|
| Enter | Enter | Collapse or expand the selected column group | ✗ | ✗ |
Related API reference
Configuration options
Core methods
Hooks
Plugins