Styling Cells, Headers, and Rows
The visible parts of the table — cells, headers, the outer frame — all accept Tailwind classes the way any component in your app does. Reach for column-level styling when a single column needs to look different (a status pill, a right-aligned number, a muted secondary line) and wrapper-level styling when the change applies to the whole table.
Column-level styling
Section titled “Column-level styling”import { DataTable, DataTableCell, DataTableColumn, DataTableColumnHeader } from '@/components/ui/data-table'
import { localModel } from '@virtuoso.dev/data-table'
const rows = [
{ name: 'Standing Desk', status: 'Launch ready', theme: 'Office' },
{ name: 'USB-C Dock', status: 'Low stock', theme: 'Peripherals' },
{ name: 'Noise-canceling Headset', status: 'Backorder', theme: 'Audio' },
]
const model = localModel({ data: rows })
export default function App() {
return (
<DataTable className="rounded-xl border-2 border-slate-900/10 shadow-sm" model={model} style={{ height: 280 }}>
<DataTableColumn field="name">
<DataTableColumnHeader>Product</DataTableColumnHeader>
<DataTableCell className="font-medium">{({ cellValue }) => String(cellValue)}</DataTableCell>
</DataTableColumn>
<DataTableColumn field="theme">
<DataTableColumnHeader>Theme</DataTableColumnHeader>
<DataTableCell>
{({ cellValue }) => <span className="rounded-full bg-slate-100 px-2 py-1 text-xs font-medium">{String(cellValue)}</span>}
</DataTableCell>
</DataTableColumn>
<DataTableColumn field="status">
<DataTableColumnHeader>Status</DataTableColumnHeader>
<DataTableCell>
{({ cellValue }) => (
<span
className={
cellValue === 'Backorder'
? 'font-medium text-red-600'
: cellValue === 'Low stock'
? 'font-medium text-amber-600'
: 'font-medium text-emerald-600'
}
>
{String(cellValue)}
</span>
)}
</DataTableCell>
</DataTableColumn>
</DataTable>
)
}className on DataTableCell and DataTableColumnHeader applies to the cell or header container — the slot the table positions and sizes. Render-function children let you wrap the value in whatever markup you need (badges, two-line layouts, conditional colors).
Wrapper-level styling
Section titled “Wrapper-level styling”className on <DataTable> reaches the outer frame around the scroll viewport. Use it for borders, rounded corners, shadow, and the table’s overall background.
<DataTable className="rounded-xl border bg-card shadow-sm" model={model}>
{/* columns */}
</DataTable>For pixel sizing, prefer style (style={{ height: 360 }}) — the table needs a measurable height to virtualize, and Tailwind’s h-* utilities work too, as long as the resolved height is real (not a percentage of an unmeasured parent).
What this page doesn’t cover
Section titled “What this page doesn’t cover”Two adjacent concerns have their own pages:
- Replacing the table’s structural components (Row, GroupHeader, sticky wrappers, scroll element) lives in Replacing Internals. That’s the
componentsprop pattern. - Default classes baked into the shadcn wrapper — change those by editing
@/components/ui/data-tabledirectly. See The shadcn Wrapper for the wrapper anatomy.