function computeStyles(scene: SceneNode, css: string | readonly string[], options?: ComputeStylesOptions): ComputedStylesComputes the styles a scene's SVG elements get from CSS, with Chartist's own CSS engine: a small one, made for chart styles. Pass the result to applyStyles.
It matches rules as a browser does, per element, with the scene below a page's html and body (so :root, html and body rules apply, and their custom properties reach the chart): type, class and attribute selectors, :root, :not(), :is() and :where(), and the descendant and child combinators, ranked by !important, the element's own style, specificity and order. Custom properties are resolved per element, and light-dark() by colorScheme. Rules in @media (prefers-color-scheme) apply for their scheme, and @supports and @layer blocks are read in place.
What it doesn't support it leaves out, and reports to onSkip: other at-rules, sibling and structural selectors (+, ~, :nth-child()), ids and other pseudo-classes, nested rules and the font shorthand. calc() and relative units such as rem are passed on as written. For full CSS, compute the styles with a browser and pass those to applyStyles(). Only the values of properties SVG has presentation attributes for are computed; elements inside a foreignObject (HTML labels) get none.
Pass only stylesheets your application controls: CSS values, url() included, end up in the markup.
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
Parameters
sceneSceneNodeA scene, usually from
toScene()cssstring | readonly string[]A stylesheet's text, or several, applied in order as if the later ones came later in the page
options?ComputeStylesOptions={}The color scheme (
lightby default), andonSkip
Returns
The values each node gets
Example
import { lineChartConfig } from 'chartist';
import { applyStyles, computeStyles, toScene } from 'chartist/server';
const css = '.ct-line { stroke: teal; } .ct-series:nth-child(2) { stroke: red; }';
const scene = toScene(lineChartConfig({ series: [[5, 2, 4]] }), {
width: 600,
height: 300
});
const styles = computeStyles(scene, css, {
// `.ct-series:nth-child(2)`: selector
onSkip: ({ text, reason }) => console.warn(`${text}: ${reason}`)
});
export const styled = applyStyles(scene, styles);function applyStyles(scene: SceneNode, styles: string | readonly string[] | ComputedStyles, options?: ComputeStylesOptions): SceneNodeWrites styles into a scene as SVG presentation attributes, so its markup draws the same in tools that read SVG on its own: rasterizers that make PNGs, PDF libraries, email. Every SVG element gets its values as attributes such as stroke="#d70206"; values of properties SVG has no attribute for are left out. Its classes stay, so a page can still style the markup, and elements inside a foreignObject (HTML labels) are left as they are: use SVG labels for images.
Give it CSS, which computeStyles computes with Chartist's own, small CSS engine, or the styles another engine computed, such as a headless browser's getComputedStyle() for each element.
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
Parameters
sceneSceneNodeA scene, usually from
toScene(); it isn't changedstylesstring | readonly string[] | ComputedStylesThe values per node from
computeStylesor another engine, or the CSS forcomputeStyles(): a stylesheet's text or several, applied in orderoptions?ComputeStylesOptions={}With CSS: the options of
computeStyles()
Returns
A copy of the scene with the styles as attributes
Example
import { readFileSync } from 'node:fs';
import { createRequire } from 'node:module';
import { lineChartConfig } from 'chartist';
import { applyStyles, renderToString, toScene } from 'chartist/server';
const css = readFileSync(
createRequire(import.meta.url).resolve('chartist/styles.css'),
'utf8'
);
const scene = toScene(
lineChartConfig({ labels: ['Mon', 'Tue', 'Wed'], series: [[5, 2, 4]] }),
{ width: 600, height: 300 }
);
// SVG for a rasterizer: the colors and widths as attributes.
export const svg = renderToString(applyStyles(scene, css));Builds a chart's scene without rendering it: no DOM, timers or globals. The same as toScene from chartist, re-exported so server code needs one import.
function renderForHydration(config: ChartConfig, size: SceneSize): stringRenders a chart to markup that chart() and the presets take over in the browser (hydration), instead of drawing a new chart. Needs no DOM, so it works in Node.js and in server bundles; put the markup into the chart's container once, and create the chart there with liveDomRenderer() from chartist/live as its renderer, which keeps the server's elements.
It lays the chart out as toScene does, at the given size. The root gets the size chart() gives it (100% unless the config sets one) and, unless the config sets a viewBox, a viewBox of the layout size, so the drawing scales into its container until the browser lays it out at the real size. Its data-ct-hydrate attribute records what the browser needs to build the same scene again: the size, the label mode, whether text was estimated and whether the viewBox only scales. Labels are HTML unless size.labels or the config says otherwise, as chart() draws them.
The markup has no style attributes, so it passes a Content Security Policy of style-src 'self', and it needs Chartist's stylesheet in the page. Styles that SVG has attributes for (a label's overflow, a donut's stroke-width) are written as those; the others, such as styles a scene listener adds, are applied when the browser takes the markup over. For a self-contained SVG image, with its styles inline (files, email, a static chart), use toScene() and renderToString instead.
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
Parameters
configChartConfigThe chart, as the browser creates it: data, axes, layers, plugins and listeners
sizeSceneSizeThe size to lay out at, in px, and how to measure text; use the estimate (no
measureText), which the browser replays
Returns
The SVG markup, its root marked with data-ct-hydrate
Example
import { lineChartConfig } from 'chartist';
import { renderForHydration } from 'chartist/server';
const data = {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
series: [[12, 9, 7, 8, 5]]
};
// On the server, in the chart's container:
export const markup = renderForHydration(lineChartConfig(data), {
width: 600,
height: 300
});
// In the browser, the chart keeps the server's elements:
// lineChart('#chart', data, { renderer: liveDomRenderer() });function renderToString(scene: SceneNode): stringSerializes a scene to standalone SVG markup. Needs no DOM, so it works in Node.js and in server bundles.
The root gets the SVG and ct: namespaces, and attribute values and text are escaped. The markup has the chart's classes but no styles: load chartist/styles.css where it's shown, or add a style element to the scene.
New in chartist/server with 2.1: the server API may still change in a 2.x minor before it becomes stable.
Parameters
sceneSceneNodeA scene, usually from
toScene()
Returns
The SVG markup, e.g. <svg xmlns="…" …>…</svg>
Example
import { lineChartConfig } from 'chartist';
import { renderToString, toScene } from 'chartist/server';
export function weekChart(values: number[]): string {
const scene = toScene(
lineChartConfig({
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
series: [values]
}),
{ width: 600, height: 300 }
);
return renderToString(scene);
}type ComputedStyles = (node: SceneNode) => Readonly<Record<string, string>> | undefinedThe styles of a scene's elements: for a scene node, the values of the CSS properties it gets (property to value, e.g. { stroke: '#d70206' }), or nothing. computeStyles makes one with Chartist's own CSS engine; another engine can make one too, for applyStyles.
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
interface SkippedStyleA part of a stylesheet that computeStyles left out, as onSkip gets it: its text and why. at-rule for an at-rule other than @media (prefers-color-scheme), @supports and @layer; selector for a selector it can't match; nested for a nested rule; shorthand for font; value for a declaration whose value doesn't resolve on an element (a var() without a value or fallback there).
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
Properties
readonly textstringThe part as written: an at-rule's prelude, a selector, a declaration.
readonly reasonSkipReasonWhy it was left out.
interface ComputeStylesOptionsOptions of computeStyles.
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
Properties
readonly colorScheme?'light' | 'dark'The color scheme to style for: which value of
light-dark()and which@media (prefers-color-scheme)rules apply.readonly onSkip?(skipped: SkippedStyle) => voidCalled once for each part of the stylesheets that was left out, so a rule that doesn't apply says why. Rules for the other color scheme and pseudo-elements (
::before), which style nothing in SVG, aren't reported.
type ApplyStylesOptions = ComputeStylesOptionsOptions of applyStyles when it gets CSS: those of computeStyles.
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
Properties
readonly colorScheme?'light' | 'dark'The color scheme to style for: which value of
light-dark()and which@media (prefers-color-scheme)rules apply.readonly onSkip?(skipped: SkippedStyle) => voidCalled once for each part of the stylesheets that was left out, so a rule that doesn't apply says why. Rules for the other color scheme and pseudo-elements (
::before), which style nothing in SVG, aren't reported.
type SkipReason = 'at-rule' | 'selector' | 'nested' | 'shorthand' | 'value'Why computeStyles() left a part of a stylesheet out: at-rule, selector, nested, shorthand or value (see SkippedStyle).
New with 2.1: the server API may still change in a 2.x minor before it becomes stable.
The size toScene and `renderForHydration()` lay a chart out at, since there's no container to measure, and how to measure text there. The same as SceneSize from chartist, re-exported so server code needs one import.