Skip to content

Column headers

Use default column headers (A, B, C), or set them to custom values provided by an array or a function.

Overview

Column headers are gray-colored rows used to label each column or group of columns. By default, these headers are populated with letters in alphabetical order.

To reflect the type or category of data in a particular column, give it a custom name and then display it in a column header. For example, instead of letters as labels such as A, B, C, ... name them ID, Full name, Country, ....

Default headers

Setting the colHeaders option to true enables the default column headers as shown in the example below:

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example1');
new Handsontable(container, {
data: [
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1', 'K1'],
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2', 'K2'],
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3', 'K3'],
],
colHeaders: true,
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example1')!;
new Handsontable(container, {
data: [
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1', 'K1'],
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2', 'K2'],
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3', 'K3'],
],
colHeaders: true,
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Header labels as an array

An array of labels can be used to set the colHeaders as shown in the example below:

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example2');
new Handsontable(container, {
data: [
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'],
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'],
],
colHeaders: ['ID', 'Full name', 'Position', 'Country', 'City', 'Address', 'Zip code', 'Mobile', 'E-mail'],
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example2')!;
new Handsontable(container, {
data: [
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'],
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'],
],
colHeaders: ['ID', 'Full name', 'Position', 'Country', 'City', 'Address', 'Zip code', 'Mobile', 'E-mail'],
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Header labels as a function

The colHeaders can also be populated using a function as shown in the example below:

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example3');
new Handsontable(container, {
data: [
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1', 'K1'],
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2', 'K2'],
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3', 'K3'],
],
colHeaders(index) {
return `Col ${index + 1}`;
},
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example3')!;
new Handsontable(container, {
data: [
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1', 'J1', 'K1'],
['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2', 'J2', 'K2'],
['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3', 'J3', 'K3'],
],
colHeaders(index) {
return `Col ${index + 1}`;
},
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Header labels in the columns option

When you configure columns individually with the columns option, set a column’s header label with that column’s title option. If both are set, a column’s title takes precedence over the matching colHeaders entry.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example6');
new Handsontable(container, {
data: [
[1, 'Ana García', 'Product Manager', 'Spain', '2022-03-14'],
[2, 'James Okafor', 'Senior Engineer', 'Nigeria', '2021-07-02'],
[3, 'Li Wei', 'Data Analyst', 'China', '2023-01-19'],
[4, 'Sofia Rossi', 'UX Designer', 'Italy', '2020-11-30'],
[5, 'Mateo Fernández', 'Engineering Lead', 'Argentina', '2019-05-08'],
],
// Set each column header label with the `title` option inside `columns`.
columns: [
{ title: 'ID' },
{ title: 'Full name' },
{ title: 'Position' },
{ title: 'Country' },
{ title: 'Start date' },
],
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example6')!;
new Handsontable(container, {
data: [
[1, 'Ana García', 'Product Manager', 'Spain', '2022-03-14'],
[2, 'James Okafor', 'Senior Engineer', 'Nigeria', '2021-07-02'],
[3, 'Li Wei', 'Data Analyst', 'China', '2023-01-19'],
[4, 'Sofia Rossi', 'UX Designer', 'Italy', '2020-11-30'],
[5, 'Mateo Fernández', 'Engineering Lead', 'Argentina', '2019-05-08'],
],
// Set each column header label with the `title` option inside `columns`.
columns: [
{ title: 'ID' },
{ title: 'Full name' },
{ title: 'Position' },
{ title: 'Country' },
{ title: 'Start date' },
],
rowHeaders: true,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Customize column headers

You can align the text in the header label with the headerClassName option. Setting it to htLeft, htCenter, or htRight will align the header labels to the left, center, or right, respectively.

You can also set the alignment for a specific column by using the columns option.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example4');
const hot = new Handsontable(container, {
data: [
['SKU-4821', 'Stainless Steel Water Bottle', 'Harbor Goods'],
['SKU-0093', 'Wireless Mouse', 'Alpine Supply Co.'],
['SKU-1170', 'Ergonomic Office Chair', 'Cascade Distributors'],
],
colHeaders: true,
rowHeaders: true,
autoWrapRow: true,
autoWrapCol: true,
height: 'auto',
headerClassName: 'htCenter',
columns: [{ headerClassName: 'htRight' }, { headerClassName: 'htLeft' }, {}],
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example4')!;
const hot = new Handsontable(container, {
data: [
['SKU-4821', 'Stainless Steel Water Bottle', 'Harbor Goods'],
['SKU-0093', 'Wireless Mouse', 'Alpine Supply Co.'],
['SKU-1170', 'Ergonomic Office Chair', 'Cascade Distributors'],
],
colHeaders: true,
rowHeaders: true,
autoWrapRow: true,
autoWrapCol: true,
height: 'auto',
headerClassName: 'htCenter',
columns: [{ headerClassName: 'htRight' }, { headerClassName: 'htLeft' }, {}],
licenseKey: 'non-commercial-and-evaluation',
});

If you want to style the header labels, you can pass any number of class names, separated by a space, to the headerClassName option.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example5');
const hot = new Handsontable(container, {
data: [
['SKU-4821', 'Stainless Steel Water Bottle', 'Harbor Goods', '142'],
['SKU-0093', 'Wireless Mouse', 'Alpine Supply Co.', '0'],
['SKU-1170', 'Ergonomic Office Chair', 'Cascade Distributors', '67'],
],
colHeaders: true,
rowHeaders: true,
autoWrapRow: true,
autoWrapCol: true,
height: 'auto',
headerClassName: 'htLeft',
columns: [
{ headerClassName: 'italic-text' },
{ headerClassName: 'bold-text italic-text' },
{ headerClassName: 'htRight bold-text italic-text' },
{},
],
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example5')!;
const hot = new Handsontable(container, {
data: [
['SKU-4821', 'Stainless Steel Water Bottle', 'Harbor Goods', '142'],
['SKU-0093', 'Wireless Mouse', 'Alpine Supply Co.', '0'],
['SKU-1170', 'Ergonomic Office Chair', 'Cascade Distributors', '67'],
],
colHeaders: true,
rowHeaders: true,
autoWrapRow: true,
autoWrapCol: true,
height: 'auto',
headerClassName: 'htLeft',
columns: [
{ headerClassName: 'italic-text' },
{ headerClassName: 'bold-text italic-text' },
{ headerClassName: 'htRight bold-text italic-text' },
{},
],
licenseKey: 'non-commercial-and-evaluation',
});
CSS
.bold-text {
font-weight: bold;
}
.italic-text {
font-style: italic;
}

Column header height

When column labels are longer, header text can wrap and require more vertical space. To control the header size, set columnHeaderHeight.

You can set this option to one of the following:

  • A number - set the same height for every column header.
  • A string - set the same height, written as a pixel size: '50' or '50px'.
  • An array - set different heights for individual column header levels.

The height is a number of pixels. A string that states a pixel size works too, so a value coming from an attribute, a JSON config, or a framework template still applies. You can mix both forms inside the array. A value that states no pixel count, such as '50%' or '20em', is ignored - the header keeps its default height, and Handsontable reports the value once in the browser console.

A negative number is kept as it is, because numbers behave exactly as they did before this option read strings. A negative string is rejected, so a typo cannot collapse the header.

The height you set is the header’s border-box height: it includes the header’s own top and bottom borders. A column header carries a 1px border on each side, so columnHeaderHeight: 40 leaves a 38px content box for the label. Before Handsontable 19.0 the bottom border was dropped while the grid sat at the top of its scroll range and added back as soon as you scrolled, so the same setting gave a 39px content box unscrolled and 38px scrolled. The header now keeps that border at every scroll position, which makes the option’s result the same wherever the grid is scrolled to. If you had tuned the number against an unscrolled grid, add a pixel to keep the label area you had.

The example below uses longer labels together with columnHeaderHeight: 50.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example7');
new Handsontable(container, {
data: [
[1, 'Ana Garcia', 'Product Manager', 'Spain', '2022-03-14'],
[2, 'James Okafor', 'Senior Engineer', 'Nigeria', '2021-07-02'],
[3, 'Li Wei', 'Data Analyst', 'China', '2023-01-19'],
[4, 'Sofia Rossi', 'UX Designer', 'Italy', '2020-11-30'],
[5, 'Mateo Fernandez', 'Engineering Lead', 'Argentina', '2019-05-08'],
],
colHeaders: ['Employee ID', 'Employee full name', 'Current job title', 'Country of residence', 'Employment start date'],
rowHeaders: true,
colWidths: [100, 130, 130, 130, 130],
columnHeaderHeight: 50,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example7')!;
new Handsontable(container, {
data: [
[1, 'Ana Garcia', 'Product Manager', 'Spain', '2022-03-14'],
[2, 'James Okafor', 'Senior Engineer', 'Nigeria', '2021-07-02'],
[3, 'Li Wei', 'Data Analyst', 'China', '2023-01-19'],
[4, 'Sofia Rossi', 'UX Designer', 'Italy', '2020-11-30'],
[5, 'Mateo Fernandez', 'Engineering Lead', 'Argentina', '2019-05-08'],
],
colHeaders: ['Employee ID', 'Employee full name', 'Current job title', 'Country of residence', 'Employment start date'],
rowHeaders: true,
colWidths: [100, 130, 130, 130, 130],
columnHeaderHeight: 50,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Nested headers

More complex data structures can be displayed with multiple headers, each representing a different category of data. To learn more about nested headers, see the column groups page.

Related guides

Related blog articles

Configuration options

Core methods

Hooks

Plugins