Styling Cells
Introduction
Section titled “Introduction”Cell styling paints a single cell — a red figure for a loss, a teal wash on a standout number, a monospace column of IDs. It comes in two layers:
- Per column (Community). Set
cellClassandcellStyleright on aColumnDef. Each is a static value applied to every cell in that column, or a callback evaluated per cell against its own value and row. No license needed. - Grid-wide (Enterprise). For value-driven rules that span all columns —
classic conditional formatting, heatmaps, cross-column highlights — use
cellStyling()and hand it to the grid ascellStyleProvider. It sees every cell, so you describe the rules once instead of wiring each column.
Both feed the same renderer, so they compose: a column’s own styling and any grid-wide provider are merged onto the cell (the provider wins on conflicts).
cellClass hooks into your stylesheet, so the styling lives in CSS and composes
with hover, selection and your design tokens. cellStyle is inline — self-contained
and highest precedence, so it always wins.
Per column (Community)
Section titled “Per column (Community)”Declare styling on the column itself:
const grid = new Zengrid(el, { columns: [ { field: 'revenue', header: 'Revenue', // Static applies to every cell; a callback is evaluated per cell. cellStyle: ({ value }) => (value as number) > 200000 ? { color: '#2d9c8f', fontWeight: 700 } : null, cellClass: ({ value }) => ((value as number) < 60000 ? 'cool' : null), }, ],});Each callback receives { row, col, field, value, data } — the cell’s value plus
its row index and record. Return the class/style, or null/undefined for none.
Style keys may be camelCase (backgroundColor) or kebab-case (background-color);
custom properties (--accent) pass through untouched. cellClass accepts a single
class, an array, or a space-separated string — they’re merged and de-duplicated.
cellStyle takes a static object (MRR) or a per-cell callback (Revenue). Change the 200000 threshold or the colours and the grid re-renders.
Grid-wide conditional formatting (Enterprise)
Section titled “Grid-wide conditional formatting (Enterprise)”When a rule spans columns — any negative number red, a revenue heatmap, dim
churned rows’ names — reach for cellStyling(). Build it once and pass it as
cellStyleProvider; it’s evaluated for every visible cell:
import { cellStyling } from '@zengrid/enterprise/grid';
const grid = new Zengrid(el, { cellStyleProvider: cellStyling({ // Class ↔ predicate: the class is added whenever the predicate matches. cellClassRules: { negative: ({ value }) => typeof value === 'number' && value < 0, }, // Or a grid-wide cellStyle callback, evaluated per cell. cellStyle: ({ value }) => typeof value === 'number' && value > 1000 ? { fontWeight: 700 } : null, }),});cellStyling() is license-gated (asserts the cell-styling feature). Its callbacks
receive the same { row, col, field, value, data } as the per-column ones, but for
every cell — use col/field to scope a rule to a column and data to read the
whole row.
Each class ↔ predicate rule adds its class to matching cells. Scroll to spot the hot/cool Revenue and low MRR. Edit the thresholds or the injected CSS.
interface CellStyleParams { row: number; // display-order row index col: number; // display-order column index field: string; // the column's field value: unknown; // the cell's displayed value data: unknown; // the full row record}
// On a ColumnDef (Community):cellClass?: CellClassValue | ((p: CellStyleParams) => CellClassValue);cellStyle?: CellStyleValue | ((p: CellStyleParams) => CellStyleValue);
// cellStyling() options (Enterprise):interface CellStylingOptions { cellClass?: CellClassValue | ((p: CellStyleParams) => CellClassValue); cellStyle?: CellStyleValue | ((p: CellStyleParams) => CellStyleValue); cellClassRules?: Record<string, (p: CellStyleParams) => boolean>;}
type CellClassValue = string | string[] | null | undefined;type CellStyleValue = Record<string, string | number> | null | undefined;- Styling lands on the cell. Classes/styles are applied to the single cell
element, so target
.zg-cell.your-classin CSS. - Precedence. Inline
cellStylewins over everything, including the theme; the grid-wide provider is applied after (and so wins over) a column’s own styling on conflicting keys.cellClasscomposes by CSS specificity. - Both layers compose. A column’s
cellClass/cellStyleand acellStyleProviderare merged onto the cell — use the column for column-local rules and the provider for anything grid-wide. - Keep callbacks cheap and pure. They run during rendering for each visible cell. Read a flag off the value/row here; do heavy work up front.
- Styling Rows — paint whole rows the same way.
- Cell Components — render richer cell content.
- Highlighting Changes — flash cells as data updates.