Skip to content

Per-datum colours

By default, every chart picks one colour per series from the active theme palette. When you want a single bar, slice, or point to render in its own colour, SwiftChart gives you four ways to express it — pick the one closest to the shape of your data.

The four layers are tried high-to-low. The first one that returns a colour wins; the rest are skipped:

LayerWhere it livesBest for
1config.colorFn callbackvalue-driven rules (“red if negative”)
2Dataset.colors[i] arraystatic, designer-picked colours per slot
3mapping.colorField (resolves into colors[])data-bound categorical colours
4Dataset.colorthe existing series-wide override
5Theme palettefallback

You can mix layers freely — for example, a colorMap for normal points plus a colorFn that highlights the row under hover.

1. colorFn — conditional colours by value

Section titled “1. colorFn — conditional colours by value”

The callback runs once per datum at draw time. Return undefined to fall through to the next layer.

new BarChart('#chart', {
colorFn: (v) => v < 0 ? '#ef4444' : v > 600 ? '#22c55e' : '#5b8cff',
}).setData(regionPnL, { x: 'region', y: 'pnl' });

The same effect using colorField — bound to a row attribute so the live preview works without serialising a function:

2. Dataset.colors — explicit per-slot palette

Section titled “2. Dataset.colors — explicit per-slot palette”

When you already know the colour for each slot at build time, pass a parallel array. Falsy entries fall through, so you can colour just a few standout points:

chart.setData([], {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [{
label: 'Revenue',
data: [120, 180, 90, 240],
colors: [undefined, undefined, '#fbbf24', undefined], // highlight Q3
}],
});

3. mapping.colorField — data-bound colours

Section titled “3. mapping.colorField — data-bound colours”

Carry the colour (or a category that maps to one) on the row itself. SwiftChart resolves it once at setData time, so there’s no per-frame cost.

The field value can be:

  • A CSS colour string (#, rgb(), hsl(), oklch(), named colours) — used verbatim.
  • A category key matched against colorMap for an explicit lookup.
  • Anything else — hashed deterministically into the theme palette so the same category always lands on the same colour across re-renders.

The resolve runs once at setData time and once again on every theme change (chart.setTheme(...) or update({ theme })) — categorical values that hash into the palette flip to the new theme’s colours; explicit colorMap entries and verbatim CSS colour strings stay put. There’s no per-frame cost either way.

const traffic = [
{ source: 'Organic', visits: 4200, status: 'good' },
{ source: 'Direct', visits: 3100, status: 'good' },
{ source: 'Social', visits: 1800, status: 'warn' },
{ source: 'Referral', visits: 1100, status: 'warn' },
{ source: 'Email', visits: 800, status: 'bad' },
{ source: 'Paid Ads', visits: 600, status: 'bad' },
];
chart.setData(traffic, {
x: 'source',
y: 'visits',
colorField: 'status',
colorMap: { good: '#22c55e', warn: '#f59e0b', bad: '#ef4444' },
});

The same API works on every chart whose datums are naturally per-slot. A pie’s slices are a good example:

new PieChart('#chart').setData(traffic, {
labelField: 'source',
valueField: 'visits',
colorField: 'source',
colorMap: {
Organic: '#5b8cff',
Direct: '#22c55e',
Social: '#f59e0b',
Referral: '#a855f7',
Email: '#06b6d4',
'Paid Ads': '#ef4444',
},
});

5. Highlighting a single point on a line chart

Section titled “5. Highlighting a single point on a line chart”

colorFn applies to dot fills on line charts (the line stroke stays at the series level so it doesn’t change colour mid-segment):

new LineChart('#chart', {
dots: true,
colorFn: (v, i) => i === 7 ? '#fbbf24' : undefined,
}).setData(monthlySales, { x: 'month', y: 'revenue' });

You can achieve the same with a colors[] array on a pre-built dataset:

chart.setData([], {
labels: months,
datasets: [{
label: 'Revenue',
data: revenue,
colors: revenue.map((_, i) => i === 7 ? '#fbbf24' : undefined),
}],
});
ChartDatum-level colouringHow
Bar, HBar, Stacked Bar, Combo (bars), Marimekko✅ each bar / cellcolorFn, colors[], colorField
Pie / Donut, Treemap, Funnel, Radial Bar✅ each slice / tilecolorFn, colorField
Scatter, Bubble✅ each pointcolorFn (overrides group palette)
Line / Area✅ each dot (stroke stays per series)colorFn, colors[]
Waterfall, Candlestick⛔ semantic (positive/negative, up/down)use theme.positive / theme.negative
Heatmap⛔ already a value→colour gradientuse colorScale
  • colorField is resolved exactly once, at setData time — it adds no per-frame cost.
  • colorFn runs once per visible datum per redraw. Keep it pure and side-effect-free.
  • Dataset.colors is a sparse array, so a single highlighted point doesn’t pay for the rest.
  • The fallback hash (hashStr) is FNV-1a — a few cycles per category.