demo D47
Colour scales
A heat map across a numeric column, between bounds you declare
formatting scale rules
The configuration
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.min.css">
<div id="grid"></div>
<script type="module">
import React from 'https://esm.sh/react@18';
import { createRoot } from 'https://esm.sh/react-dom@18/client';
import { createGrid } from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.esm.min.js';
import createLatticeGrid from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/modules/react.esm.min.js';
const LatticeGrid = createLatticeGrid({ React, createGrid });
const formatting = {
// A scale states its own bounds. They are not derived from the rows, so
// filtering the column does not rescale the colours. The two ink rules run
// after the scale and carry stopIfTrue: false so the scale is still reached:
// this is the layering the ordered list is for.
monthlyCost: [
{ id: 'cost-scale', scale: { min: 0, max: 42000, colours: ['#f5f7fa', '#1a6bc7'] } },
{ id: 'cost-ink-high', when: { op: 'gte', value: 21000 }, style: { color: '#ffffff' }, stopIfTrue: false },
{ id: 'cost-ink-low', when: { op: 'lt', value: 21000 }, style: { color: '#16202b' }, stopIfTrue: false },
],
// Three stops rather than two: the middle colour is reached at the middle of
// the range, which is what makes a latency column read as good, borderline, bad.
p99Ms: [
{ id: 'p99-scale', scale: { min: 90, max: 4100, colours: ['#e8f5ee', '#fdf3e0', '#fbeceb'] } },
{ id: 'p99-ink', when: { op: 'notBlank' }, style: { color: '#16202b' }, stopIfTrue: false },
],
};
const columns = [
{ field: 'service', title: 'Service', layout: { pin: 'start', width: 140 } },
{ field: 'team', title: 'Team', filter: { type: 'set' } },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{ field: 'p99Ms', title: 'p99 ms', type: 'number', filter: { type: 'number' } },
{ field: 'monthlyCost', title: 'Monthly cost', type: 'number', filter: { type: 'number' },
format: { style: 'currency', currency: 'USD' }, total: 'sum' },
];
const rows = [/* service records */];
function App() {
return (
<LatticeGrid
rowKey="id"
formatting={formatting}
columns={columns}
rows={rows}
style={{ height: '540px' }}
/>
);
}
createRoot(document.getElementById('grid')).render(<App />);
</script>
Heat-mapping a numeric column with colour scales
A colour scale shades each cell in a numeric column by where its value sits between a declared minimum and maximum, so a column of margins or temperatures reads as a heat map rather than a list of digits. A developer reaches for it when the pattern across a column matters more than any single figure: spotting the worst-performing row in a sales sheet, or the outlier reading in a sensor log, without scanning every number by eye. Lattice Grid configures this through formatting scale rules, a column option taking the bounds and a colour range and interpolating the background for every cell, so the shading updates as values change rather than needing a fixed lookup table. The interpolation runs once per cell against the declared bounds, so a scale over several thousand rows costs the same per cell as a plain formatter, and the JavaScript data grid does not recompute the range on every scroll or resize. Colour alone never carries the only signal: the underlying value stays visible in the cell text, so a viewer relying on a screen reader or unable to distinguish the colour range still gets the figure the shading describes. Bounds can be fixed values or derived from the data, tracking a known target range or the spread present in the current rows.
How do I add a colour scale or heat map to a data grid column?
Apply a formatting scale rule to the column, giving it a minimum, a maximum and the colours to interpolate between. Lattice Grid shades each cell’s background by where its value falls in that range, recalculating per cell without a separate lookup pass. Bounds can be fixed numbers or derived from the visible data, and the cell text stays legible so the colour is a supplement to the value, not a replacement for it.