Chartist

Search

Find a guide, an API entry or an example.

Try

chartist/server

Charts as markup without a DOM: SVG strings, markup the browser takes over, and stylesheets written into the SVG for images and PDFs.

computeStyles

experimentalchartist/serverSource
function computeStyles(scene: SceneNode, css: string | readonly string[], options?: ComputeStylesOptions): ComputedStyles

Computes 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

scene SceneNode

A scene, usually from toScene()

css string | 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 (light by default), and onSkip

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);

applyStyles

experimentalchartist/serverSource
function applyStyles(scene: SceneNode, styles: string | readonly string[] | ComputedStyles, options?: ComputeStylesOptions): SceneNode

Writes 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

scene SceneNode

A scene, usually from toScene(); it isn't changed

styles string | readonly string[] | ComputedStyles

The values per node from computeStyles or another engine, or the CSS for computeStyles(): a stylesheet's text or several, applied in order

options? 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));

toScene

chartist/serverSource

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.

renderForHydration

experimentalchartist/serverSource
function renderForHydration(config: ChartConfig, size: SceneSize): string

Renders 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

config ChartConfig

The chart, as the browser creates it: data, axes, layers, plugins and listeners

size SceneSize

The 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() });

renderToString

experimentalchartist/serverSource
function renderToString(scene: SceneNode): string

Serializes 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

scene SceneNode

A 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);
}

ComputedStyles

experimentalchartist/serverSource
type ComputedStyles = (node: SceneNode) => Readonly<Record<string, string>> | undefined

The 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.

SkippedStyle

experimentalchartist/serverSource
interface SkippedStyle

A 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 text string

The part as written: an at-rule's prelude, a selector, a declaration.

readonly reason SkipReason

Why it was left out.

ComputeStylesOptions

experimentalchartist/serverSource
interface ComputeStylesOptions

Options 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) => void

Called 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.

ApplyStylesOptions

experimentalchartist/serverSource
type ApplyStylesOptions = ComputeStylesOptions

Options 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) => void

Called 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.

SkipReason

experimentalchartist/serverSource
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.

SceneSize

chartist/serverSource

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.