Chartist

Search

Find a guide, an API entry or an example.

Try

Rendering

From scene to output: renderers, text measuring, and rendering on the server.

Chartist renders a scene as SVG in the page or as a string on the server. @chartist-js/terminal renders the same scene as text for terminals and as text art in HTML.

toScene

Source
function toScene(config: ChartConfig, size: SceneSize): SceneNode

Builds a chart's scene without rendering it: no DOM, timers or globals. Runs the phases resolve to scene with the config's plugins and listeners.

It takes the same config as chart(), and the SVG gets the same chart type class without className. Listeners of render and mount never run, responsive overrides and the renderer are ignored, and calling update(), detach() or destroy() on the handle a plugin gets throws. Turn the scene into markup with renderToString() from chartist/server, which re-exports this function.

Parameters

config ChartConfig

The chart: data, axes, layers, plugins and listeners

size SceneSize

The size to lay out at, in px, and how to measure text

Returns

The scene, its root the svg

Example

import { lineChartConfig, node, toScene } from 'chartist';
import { renderToString } from 'chartist/server';

const config = lineChartConfig(
  { labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], series: [[12, 9, 7, 8, 5]] },
  {
    viewBox: { width: 600, height: 300 },
    on: {
      // Styles inside the SVG, for tools that read it on its own.
      scene: ({ scene }) => ({
        scene: scene.append(
          node('style').text('.ct-line { fill: none; stroke: #d70206; }'),
          true
        )
      })
    }
  }
);
const scene = toScene(config, { width: 600, height: 300 });

export const markup = renderToString(scene);

seriesColors

Source
const seriesColors: readonly string[]

The default series colors, a to o, as hex: the colors of chartist/styles.css ($ct-series-colors in the Sass settings). Renderers without CSS use them to color series the way the styles do. The styles color the first fifteen series only.

Example

import { seriesColors } from 'chartist';

// The color of series `c`, the third.
export const third = seriesColors[2];

applyAttribute

Source
function applyAttribute(element: Element, name: string, value: string | number): void

Sets one scene attribute on an element as the DOM renderer does: names with a known prefix (ct:value) in their namespace, and style through the CSSOM, which a Content Security Policy allows. For renderers that change elements they keep.

Parameters

element Element

The element to change

name string

The attribute's name, as in a scene node's attrs

value string | number

The attribute's value

Example

import { applyAttribute } from 'chartist';

const point = document.querySelector('.ct-point');
if (point) {
  applyAttribute(point, 'ct:value', 12);
  applyAttribute(point, 'style', 'stroke-width: 12px;');
}

renderElement

Source
function renderElement(current: SceneNode, document: Document, options?: RenderElementOptions): Element

Creates the element tree of a scene node as the DOM renderer does: SVG elements, HTML elements inside a foreignObject, attributes set with applyAttribute. For renderers that create elements.

Parameters

current SceneNode

The node to create

document Document

The document to create the elements in

options? RenderElementOptions = {}

The namespace, and a callback for each created element

Returns

The node's element, with its children

Example

import { node, renderElement } from 'chartist';

const dot = renderElement(node('circle', { cx: 5, cy: 5, r: 4 }, 'ct-dot'), document);
document.querySelector('svg')?.append(dot);

domRenderer

Source
function domRenderer(): Renderer<DomRenderOutput>

Creates the renderer chart() uses by default: it renders scenes as inline SVG into the container, replacing an earlier Chartist SVG there (as 1.x does) on every render, and measures text and reads styles for layout in the container, so its CSS applies. It ignores the previous render it gets from a chart's second render on; liveDomRenderer() from chartist/live keeps its SVG and changes it instead. Wrap it to change what every render puts on the page.

Example

import { chart, domRenderer, pie, type Renderer } from 'chartist';

const dom = domRenderer();
// The DOM renderer, with a name for screen readers on every render.
const renderer: Renderer = {
  ...dom,
  render(scene, container) {
    const output = dom.render(scene, container);
    output.svg.setAttribute('role', 'img');
    output.svg.setAttribute('aria-label', 'Monthly budget');
    return output;
  }
};

chart('#chart', {
  data: { series: [50, 30, 20] },
  coordinates: 'polar',
  layers: [pie()],
  renderer
});

textAscent

Source
const textAscent: 0.85

Where SVG text labels put a line's baseline: this share of the font size below the top of the line (a typical font's ascent). Lines are one font size apart, so a renderer finds a line's vertical center at y - (textAscent - 0.5) * fontSize from its y.

estimateText

Source
const estimateText: MeasureText

Estimates text size without a DOM: an average glyph is 0.6 em wide, and a line is 1.2 em high, at fontSize or else 12 px. toScene() measures with it unless you pass your own, which can build on it.

Example

import { estimateText, type MeasureText } from 'chartist';

// Bold labels: a tenth wider than the estimate.
export const measureText: MeasureText = (text, options) => {
  const size = estimateText(text, options);
  return { ...size, width: size.width * 1.1 };
};

SceneSize

Source
interface SceneSize

The size toScene and renderForHydration() lay a chart out at, since there's no container to measure, and how to measure text there.

Properties

readonly width number

The width to lay out at, in px. In toScene(), the root svg gets it as its width, unless the config sets one.

readonly height number

The height to lay out at, in px. In toScene(), the root svg gets it as its height, unless the config sets one.

readonly measureText? MeasureText

Text measurement for layout; an estimate by default.

readonly labels? LabelMode

Label mode when the config sets none. svg by default in toScene(), since string output often goes to tools without HTML support; html in renderForHydration(), as chart() draws them.

DomRenderOutput

Source
interface DomRenderOutput extends RenderOutput

What domRenderer returns from render(): the inline SVG it added to the container.

Properties

readonly svg SVGSVGElement

The chart's svg element, in the container.

readonly elementOf (node: SceneNode) => Element | undefined

The rendered element of a scene node of this render.

readonly remove () => void

Takes the SVG out of the container again.

readonly patched? boolean

true when the renderer changed its previous output in place with the update it got, instead of replacing it. Then changes says what it did.

readonly changes? readonly SceneChange[]

What the renderer did to each changed node, with patched. Without them, the chart describes the render as a replacement.

readonly animation? UpdateAnimation

The timing of the update animation the renderer started, if any. The mount event passes it on as animation.

RenderElementOptions

Source
interface RenderElementOptions

What renderElement takes besides the node and the document.

Properties

readonly html? boolean

Creates the elements in the XHTML namespace, as inside a foreignObject.

readonly created? (node: SceneNode, element: Element) => void

Called for every node and the element created for it.

TextMetrics

Source
interface TextMetrics

The size of a measured text, as a MeasureText function returns it.

Properties

readonly width number

The text's width in px.

readonly height number

The text's height in px: one line.

readonly fontSize? number

The font size in px the text was measured with, when known.

LabelMode

Source
type LabelMode = 'html' | 'svg'

How labels are drawn: HTML in a foreignObject (1.x) or SVG text.

MeasureTextOptions

Source
interface MeasureTextOptions

What a MeasureText function gets with the text to measure.

Properties

readonly classes? readonly string[]

Class names of the text, for renderers that apply CSS.

readonly fontSize? number

Font size in px. Without it, the browser measures with the CSS font size and the estimate uses 12, the size of 1.x .ct-label.

readonly rootClass? string

Classes of the chart's root svg, so chart-type CSS applies.

readonly container? Element

Where to measure (the chart container), so its CSS applies.

MeasureText

Source
type MeasureText = (text: string, options?: MeasureTextOptions) => TextMetrics

Measures how much space a text takes, in px, so labels can be wrapped and aligned. In the browser, Chartist measures with the page's fonts; toScene() estimates (0.6 em per character, 1.2 em per line) unless you pass your own in its size.

Example

import type { MeasureText } from 'chartist';

// Wider glyphs than the estimate, for a wide font.
export const measureText: MeasureText = (text, options = {}) => {
  const fontSize = options.fontSize ?? 12;
  return { width: text.length * fontSize * 0.7, height: fontSize * 1.25 };
};

MeasureStyleOptions

Source
interface MeasureStyleOptions

What a MeasureStyle function gets with the property to read.

Properties

readonly classes? readonly string[]

Class names of the element whose style is read.

readonly rootClass? string

Classes of the chart's root svg, so chart-type CSS applies.

readonly container? Element

Where to measure (the chart container), so its CSS applies.

MeasureStyle

Source
type MeasureStyle = (property: string, options?: MeasureStyleOptions) => string | undefined

Reads a computed CSS property of an SVG path with the given classes, for values that the stylesheet decides and layout needs: the pie layer reads the stroke-width of a donut slice to fit the ring. Returns undefined when it can't tell. In the browser, Chartist reads it in the chart's container; toScene() has no stylesheet, so layout uses its defaults there.

Example

import { domRenderer, type Renderer } from 'chartist';

// The DOM renderer, but donuts are laid out for 30px rings, whatever
// the stylesheet says. Pass it as `renderer` to `chart()`.
export const renderer: Renderer = {
  ...domRenderer(),
  measureStyle: property => (property === 'stroke-width' ? '30px' : undefined)
};

RenderCause

Source
type RenderCause = 'create' | 'hydrate' | 'update' | 'resize' | 'responsive' | 'fonts'

Why a chart rendered: create for its first render, hydrate for the first render of a chart that took server markup over (see renderForHydration()), update for update() (and the presets' setOptions()), resize when its container's size changed, responsive when its matching responsive entries changed, fonts when web fonts finished loading.

SceneChange

Source
interface SceneChange

What a render did to one node of the output: add for a node the previous scene didn't have, update for a node whose attributes, classes or text changed (with its previous node), remove for a node of the previous scene that's gone.

Properties

readonly op 'remove' | 'update' | 'add'

What happened to the node.

readonly node SceneNode

The node: of the new scene, or of the previous one for remove.

readonly previous? SceneNode

The node in the previous scene, for update.

Keyframes

Source
type Keyframes = readonly Readonly<Record<string, AttrValue>>[]

The keyframes of a node's update animation: one set of attributes per progress point, in the order of the points.

UpdateAnimation

Source
interface UpdateAnimation

The timing of a render's update animation: its duration in ms and its easing as a CSS easing, such as ease-out.

Properties

readonly duration number

The duration in ms.

readonly easing string

The CSS easing, such as ease-out or cubic-bezier(0.3, 0, 0.2, 1).

RenderUpdate

Source
interface RenderUpdate<TOutput extends RenderOutput = RenderOutput>

What a renderer gets about the previous render, from a chart's second render on. A renderer can change its previous output in place with it, instead of replacing it; renderers keep no state themselves.

Properties

readonly previous TOutput

What this renderer returned for the previous render.

readonly previousScene SceneNode

The previous render's scene.

readonly cause RenderCause

Why the chart renders.

readonly labels readonly unknown[]

The data's labels, for keys from labels.

readonly previousLabels readonly unknown[]

The previous render's labels, for keys from labels in the previous scene.

readonly keyframes (previous: SceneNode, next: SceneNode, progress: readonly number[]) => Keyframes | undefined

Asks the chart's plugins, then the layer that drew the node, for the keyframes of a node's update at the given progress points (0 is the previous node, 1 the new one; points may lie beyond them when the easing overshoots). Returns nothing when none of them has any.

RenderOutput

Source
interface RenderOutput

What a renderer returns from render(). The render and mount phase events pass it on as output.

Properties

readonly elementOf? (node: SceneNode) => Element | undefined

The rendered element of a scene node, if the output is DOM.

readonly remove? () => void

Removes the output again.

readonly patched? boolean

true when the renderer changed its previous output in place with the update it got, instead of replacing it. Then changes says what it did.

readonly changes? readonly SceneChange[]

What the renderer did to each changed node, with patched. Without them, the chart describes the render as a replacement.

readonly animation? UpdateAnimation

The timing of the update animation the renderer started, if any. The mount event passes it on as animation.

Renderer

Source
interface Renderer<TOutput extends RenderOutput = RenderOutput>

Turns a scene into output. chart() renders inline SVG into its container with the DOM renderer, unless its config sets a renderer. To get markup instead, without a DOM, use toScene() and renderToString() from chartist/server. A renderer that wraps another one keeps its adopt only if it passes it on, as spreading the wrapped renderer does.

Properties

render (scene: SceneNode, target: Element, update?: RenderUpdate<TOutput>) => TOutput

Renders a scene into the chart's container, after the scene phase and on every update and resize. From the second render on, it gets the previous render as update: a renderer that changes its previous output in place returns patched: true and its changes; one that ignores update replaces its output, as the DOM renderer does.

readonly measureText? MeasureText

Measures text for layout, in the container so its CSS applies; without it, Chartist estimates text sizes.

readonly measureStyle? MeasureStyle

Reads computed styles for layout, in the container so its CSS applies; without it, layout uses its defaults (a donut's ring is laid out for 60 px).

readonly labels? LabelMode

The default label mode of this renderer; html if omitted.

adopt? (container: Element, replay: (layout: { readonly width: number; readonly height: number; readonly labels: LabelMode }) => SceneNode) => TOutput & { readonly repaired: number } | undefined

Takes over markup from renderForHydration() in the chart's container, instead of rendering: finds it and reads the layout its marker records, gets the scene for that layout from replay, binds the scene's nodes to the markup's elements and makes them what render() would draw. A chart calls it once, before its first render, unless it always draws a new svg; later renders go through render(), with the adopted output as the previous one. Returns nothing when there's no markup to take over or it doesn't match the scene, and the chart then renders as usual. liveDomRenderer() from chartist/live has it; the DOM renderer doesn't, since it replaces its svg on every render.