Skip to content

Column Layout

Column width has two parts: the base width and the realized width.

The base width comes from the column header. The table measures DataTableColumnHeader, then uses that measured width as the starting point for both the header and every body cell in that column.

The realized width is the width the column gets after the table compares all base widths with the viewport. When the viewport is wider than the total base width, extra space is distributed by the table. When the viewport is narrower, columns keep their base widths and the table scrolls horizontally.

Use header width classes for the minimum useful size of each column:

<DataTableColumn field="name">
  <DataTableColumnHeader className="min-w-72">Name</DataTableColumnHeader>
  <DataTableCell>{NameCell}</DataTableCell>
</DataTableColumn>

<DataTableColumn field="updated">
  <DataTableColumnHeader className="w-44">Updated</DataTableColumnHeader>
  <DataTableCell>{UpdatedCell}</DataTableCell>
</DataTableColumn>

Do not mirror those widths on DataTableCell. Body cells render inside tracks sized by the table. Cell width utilities can fight those tracks and cause clipping or overlap.

Use DataTableColumn grow={number} for columns that should absorb extra viewport width. The value is a ratio, not a CSS flex shorthand. Omitting grow, or passing grow={0}, keeps the column fixed when another visible column grows.

<DataTableColumn field="name" grow={1}>
  <DataTableColumnHeader className="min-w-72">Name</DataTableColumnHeader>
  <DataTableCell>{NameCell}</DataTableCell>
</DataTableColumn>

<DataTableColumn field="description" grow={3}>
  <DataTableColumnHeader className="min-w-80">Description</DataTableColumnHeader>
  <DataTableCell>{DescriptionCell}</DataTableCell>
</DataTableColumn>

<DataTableColumn field="versions">
  <DataTableColumnHeader className="w-40">Versions</DataTableColumnHeader>
  <DataTableCell>{VersionBadgesCell}</DataTableCell>
</DataTableColumn>

<DataTableColumn field="updated">
  <DataTableColumnHeader className="w-44">Updated</DataTableColumnHeader>
  <DataTableCell>{UpdatedCell}</DataTableCell>
</DataTableColumn>

<DataTableColumn id="actions">
  <DataTableColumnHeader className="w-16 justify-center">Actions</DataTableColumnHeader>
  <DataTableCell>{ActionsCell}</DataTableCell>
</DataTableColumn>

In this layout, name and description receive all extra width. description receives three times as much extra width as name. versions, updated, and actions keep their base widths.

Choose grow columns from the local data and workflow. IDs, slugs, checkboxes, action menus, short labels, badges, version counts, timestamps, and compact metadata usually should not grow. Names, titles, descriptions, summaries, messages, notes, paths, and other text-heavy content usually benefit from extra room. The field name is only a clue: a short code-like name may be fixed, while a user-authored label column may deserve room.

Do not make every column grow. The point of grow is to let useful text columns breathe while compact columns stay compact.

Tables that do not set grow preserve the default auto-fill behavior: when the viewport is wider than the total base width, extra space is distributed evenly across visible columns. This keeps existing tables filling their container without changing every column declaration.

Once any visible column has a positive finite grow value, only grow columns receive leftover width. Non-grow columns keep their base widths.

grow only distributes extra space. It does not shrink columns below their base widths, and there is no shrink table API.

When the viewport narrows, grow space disappears first. After the total base width no longer fits, the table keeps base widths and uses horizontal scrolling.

Column resizing sets the rendered width of that column. During and after a resize override, the table preserves the current rendered widths of the other columns instead of redistributing grow space on every pointer move. That keeps the resize handle under the pointer and lets wider columns push the table into horizontal overflow.

Clear the resize override to return the column to its measured base width and the normal grow distribution.

Persist resize overrides as user-selected widths, not as automatic grow output. The saved width is the user’s explicit override; automatic grow space is recalculated only when no resize override is active for that layout.