Styling the Chart
The theme colours the chart. Beyond colours, the chart has options for its axes, legend, crosshair and background:
| To change | Use |
|---|---|
| Candle colours | The theme's studies.; see Creating a Custom Theme |
| One indicator's colours | Its constructor's colours, or the theme's studies. for every chart; below |
| Axis gridlines, bands, labels and fonts | axis, apply |
| The legend and crosshair | The theme's chart colours, and Fin's setters |
| The background | The theme's chart., or surface |
| Drawings and the order book heatmap | The theme; below |
TypeScript Example: Styling the Chart
BTC-USD with an orange SMA, its colour passed to the study, and axisDefaults turning off the axis bands and minor gridlines. The buttons switch theme, turn the gridlines on and off with applyAxisStyle, and enlarge the axis labels and legend. Switch theme after the others: the orange SMA and your axis options stay.
The code for this example is found below.
- TS
import "scichart-scitrader/scitrader.css";
import {
applyThemeCssVariables,
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
FinChartLegendModifier,
idbPriceStore,
ISciTraderTheme,
OHLCStudy,
RSIStudy,
SciFinanceChartPanel,
SCITRADER_DARK_THEME,
SCITRADER_LIGHT_THEME,
SMAStudy,
VolumeStudy,
} from "scichart-scitrader";
// This example expects this HTML:
// <div style="display: flex; flex-direction: column; height: 100%">
// <div id="toolbar"></div>
// <div id="chart" style="flex: 1; min-height: 0"></div>
// </div>
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
async function createChart() {
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
theme: SCITRADER_DARK_THEME,
// 1. Axis options for every axis, on every pane: any SciChart axis option. These win over the theme
axisDefaults: {
drawMajorBands: false, // no alternating bands
drawMinorGridLines: false,
},
studies: [
new OHLCStudy(),
new VolumeStudy(),
// 2. A colour passed to a study is your choice: a theme switch leaves it alone
new SMAStudy({ length: 20, renderOptions: { stroke: "#F59E0B", strokeThickness: 2 } }),
new RSIStudy(),
],
});
const chart = financeChartPanel.financeApi;
// 3. The legend is drawn by FinChartLegendModifier: its setters style it
const legend = chart.finChartModifiers
.asArray()
.find((m): m is FinChartLegendModifier => m instanceof FinChartLegendModifier);
let theme = SCITRADER_DARK_THEME;
let gridLines = true;
let largeText = false;
const actions: Array<[string, boolean, () => void]> = [
// A theme switch restyles the chart, but keeps axisDefaults, applyAxisStyle and the orange SMA
["Dark", theme === SCITRADER_DARK_THEME, () => setTheme(SCITRADER_DARK_THEME)],
["Light", theme === SCITRADER_LIGHT_THEME, () => setTheme(SCITRADER_LIGHT_THEME)],
// applyAxisStyle changes axis options on a live chart
[
"Gridlines",
gridLines,
() => {
gridLines = !gridLines;
chart.applyAxisStyle({ drawMajorGridLines: gridLines });
},
],
[
"Large text",
largeText,
() => {
largeText = !largeText;
const fontSize = largeText ? 15 : theme.chart.axisLabelFontSize;
chart.applyAxisStyle({ labelStyle: { fontSize } }); // axis labels
legend?.setLegendFontSize(largeText ? 15 : theme.chart.legendFontSize); // the legend
legend?.setAxisLabelFont(fontSize); // the crosshair's labels on the axes
},
],
];
function setTheme(next: ISciTraderTheme) {
theme = next;
chart.setTheme(next);
// setTheme sets the legend to the theme's size: keep the larger text if it is on
legend?.setLegendFontSize(largeText ? 15 : next.chart.legendFontSize);
applyThemeCssVariables(document.body, next); // for the toolbar
}
function renderToolbar() {
const toolbar = document.getElementById("toolbar");
Object.assign(toolbar.style, toolbarStyle);
toolbar.replaceChildren(
...actions.map(([label, , action]) => {
const button = document.createElement("button");
button.textContent = label;
Object.assign(button.style, buttonStyle(isOn(label)));
button.onclick = () => {
action();
renderToolbar();
};
return button;
})
);
}
const isOn = (label: string) =>
({
Dark: theme === SCITRADER_DARK_THEME,
Light: theme === SCITRADER_LIGHT_THEME,
Gridlines: gridLines,
"Large text": largeText,
})[label];
applyThemeCssVariables(document.body, theme);
renderToolbar();
// When the page goes away: financeChartPanel.cleanup();
return financeChartPanel;
}
// The toolbar's colours are the theme's CSS variables, so it follows the theme too
const toolbarStyle: Partial<CSSStyleDeclaration> = {
display: "flex",
flexWrap: "wrap",
gap: "4px",
padding: "8px 12px",
background: "var(--st-ui-toolbar-background)",
borderBottom: "1px solid var(--st-ui-divider)",
};
const buttonStyle = (selected: boolean): Partial<CSSStyleDeclaration> => ({
padding: "4px 12px",
border: "1px solid var(--st-ui-divider)",
borderRadius: "4px",
background: selected ? "var(--st-ui-accent)" : "var(--st-ui-button-background)",
color: selected ? "#ffffff" : "var(--st-ui-toolbar-text)",
font: "13px var(--st-font-family, sans-serif)",
cursor: "pointer",
});
createChart();
React Example: Styling the Chart
The same in React: each setting is state, applied to the chart in an effect.
The code for this example is found below.
- React
import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
FinChartLegendModifier,
idbPriceStore,
ISciFinanceChartPanelApi,
ISciFinanceChartPanelConfig,
ISciTraderTheme,
OHLCStudy,
RSIStudy,
SCITRADER_DARK_THEME,
SCITRADER_LIGHT_THEME,
SMAStudy,
VolumeStudy,
} from "scichart-scitrader";
import { SciFinanceChartView, SciTraderThemeProvider } from "scichart-scitrader-react";
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
export function ChartStylingChart() {
const [api, setApi] = React.useState<ISciFinanceChartPanelApi>();
const [theme, setTheme] = React.useState<ISciTraderTheme>(SCITRADER_DARK_THEME);
const [gridLines, setGridLines] = React.useState(true);
const [largeText, setLargeText] = React.useState(false);
// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
theme: SCITRADER_DARK_THEME,
// 1. Axis options for every axis, on every pane: any SciChart axis option. These win over the theme
axisDefaults: {
drawMajorBands: false, // no alternating bands
drawMinorGridLines: false,
},
studies: [
new OHLCStudy(),
new VolumeStudy(),
// 2. A colour passed to a study is your choice: a theme switch leaves it alone
new SMAStudy({ length: 20, renderOptions: { stroke: "#F59E0B", strokeThickness: 2 } }),
new RSIStudy(),
],
}),
[]
);
// A theme switch restyles the chart, but keeps axisDefaults, applyAxisStyle and the orange SMA
React.useEffect(() => api?.financeApi.setTheme(theme), [api, theme]);
// applyAxisStyle changes axis options on a live chart
React.useEffect(() => api?.financeApi.applyAxisStyle({ drawMajorGridLines: gridLines }), [api, gridLines]);
// 3. The legend is drawn by FinChartLegendModifier: its setters style it
React.useEffect(() => {
if (!api) return;
const chart = api.financeApi;
const legend = chart.finChartModifiers
.asArray()
.find((m): m is FinChartLegendModifier => m instanceof FinChartLegendModifier);
const fontSize = largeText ? 15 : theme.chart.axisLabelFontSize;
chart.applyAxisStyle({ labelStyle: { fontSize } }); // axis labels
legend?.setLegendFontSize(largeText ? 15 : theme.chart.legendFontSize); // the legend
legend?.setAxisLabelFont(fontSize); // the crosshair's labels on the axes
}, [api, largeText, theme]);
return (
// The provider gives the toolbar the theme's CSS variables
<SciTraderThemeProvider theme={theme}>
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
<div style={toolbarStyle}>
<Toggle text="Dark" on={theme === SCITRADER_DARK_THEME} onClick={() => setTheme(SCITRADER_DARK_THEME)} />
<Toggle text="Light" on={theme === SCITRADER_LIGHT_THEME} onClick={() => setTheme(SCITRADER_LIGHT_THEME)} />
<Toggle text="Gridlines" on={gridLines} onClick={() => setGridLines(!gridLines)} />
<Toggle text="Large text" on={largeText} onClick={() => setLargeText(!largeText)} />
</div>
<div style={{ flex: 1, minHeight: 0 }}>
<SciFinanceChartView config={config} onInit={setApi} />
</div>
</div>
</SciTraderThemeProvider>
);
}
function Toggle({ text, on, onClick }: { text: string; on: boolean; onClick: () => void }) {
return (
<button style={buttonStyle(on)} onClick={onClick}>
{text}
</button>
);
}
// The toolbar's colours are the theme's CSS variables, so it follows the theme too
const toolbarStyle: React.CSSProperties = {
display: "flex",
flexWrap: "wrap",
gap: 4,
padding: "8px 12px",
background: "var(--st-ui-toolbar-background)",
borderBottom: "1px solid var(--st-ui-divider)",
};
const buttonStyle = (selected: boolean): React.CSSProperties => ({
padding: "4px 12px",
border: "1px solid var(--st-ui-divider)",
borderRadius: 4,
background: selected ? "var(--st-ui-accent)" : "var(--st-ui-button-background)",
color: selected ? "#ffffff" : "var(--st-ui-toolbar-text)",
font: "13px var(--st-font-family, sans-serif)",
cursor: "pointer",
});
Indicator Colours
An indicator's colours come from the theme, studies.<type>, unless you pass your own:
new SMAStudy({ length: 20, renderOptions: { stroke: "#F59E0B", strokeThickness: 2 } });
A colour passed to a constructor is kept through every theme switch, as are colours the user edits in the indicator's settings form. To change an indicator's colours on every chart, put them in your theme instead: studies: { SMA: { strokeColor: "#F59E0B" } }. The keys are the colour names in each indicator's settings form; Creating a Custom Theme lists them.
Axes
axisDefaults takes any SciChart axis option, IAxisBase2dOptions, for every axis on every pane, including panes added later. It wins over the theme's axis colours:
const financeChartPanel = await SciFinanceChartPanel.create(element, {
// …
axisDefaults: {
drawMajorBands: false, // no alternating bands
drawMinorGridLines: false,
labelStyle: { fontSize: 13 },
},
});
// Later, on a live chart: only the options given change
financeChartPanel.financeApi.applyAxisStyle({ drawMajorGridLines: false });
Fonts. Axis labels are drawn by WebGL, so a font must be registered with SciChart (sciChartSurface.registerFont) before labelStyle.fontFamily can use it. The theme's fontFamily is for the HTML controls only. Each theme sets the label size as chart.axisLabelFontSize.
The Legend and Crosshair
The theme sets their colours: chart.crosshair, crosshairDot, crosshairLabelBackground, crosshairLabelText and legendText, and the legend's size, chart.legendFontSize. The crosshair is a thin dashed line. FinChartLegendModifier, which draws both, has setters for the legend and the crosshair's axis labels:
const legend = financeChartPanel.financeApi.finChartModifiers
.asArray()
.find((m): m is FinChartLegendModifier => m instanceof FinChartLegendModifier);
legend.setLegendFontSize(15);
legend.setAxisLabelFont(15); // the crosshair's labels on the axes
legend.legendOffsetX = 12; // move the legend
- A theme switch sets the legend's colours and size back to the theme's, so set them again after
setThemeif you changed them. - After
setThemeto a theme with a differentlegendFontSize, callsetLegendFontSizewith it too: the legend doesn't redraw at the new size by itself yet. - To hide the crosshair and legend, e.g. on a touch screen, call
setCursorEnabled(false); see Mobile and Desktop Modes.
The legend styling members of FinChartLegendModifier, with their TSDoc
class FinChartLegendModifier {
/**
* Colours of the crosshair's axis labels (the price and time tags on the axes). The labels
* are baked into their annotations when created, so this rebuilds the crosshair on every pane.
*/
setAxisLabelColors(fill: string, text: string): void;
/**
* Live-updates the y-axis price tag's font on every pane. A `HorizontalLineAnnotation` draws
* its tag in its own `axisFontSize` / `axisFontFamily` (SciChart's default 14px), not the
* axis `labelStyle` the earlier `LineAnnotation` tag used, so `SciFinanceChart` passes the
* axis label font in here whenever it sets one: at creation, `setTheme` and
* `applyAxisStyle`. The axis font is drawn by WebGL, so CSS can't reach it.
*/
setAxisLabelFont(fontSize: number | undefined, fontFamily?: string): void;
/**
* Live-updates the text color used by the legend annotation on every attached
* pane. The template reads `la.valueFill` per-render, but SciChart only
* re-renders the SVG when the annotation's `template` property fires its
* change notification — so we re-assign the template to itself after writing
* the new color, forcing the next paint to pick it up.
*/
setLegendTextColor(value: string): void;
/** Live-updates the legend row font size on every attached pane's legend annotation. */
setLegendFontSize(value: number): void;
get legendOffsetX(): number;
set legendOffsetX(value: number);
get legendOffsetY(): number;
set legendOffsetY(value: number);
/**
* Master on/off for the cursor readout. When `enabled` is `false`, the
* per-pane legend and the crosshair are hidden completely and pointer moves
* are ignored — the chart shows no cursor/legend. When `true`, the legend
* renders again (latest value at rest, hovered value on pointer-move) and
* the crosshair tracks the pointer.
*
* This modifier — not SciChart's built-in `CursorModifier` (never
* instantiated here) — owns both the crosshair and the legend, so the
* cursor-toggle button routes through this method.
*/
setCursorEnabled(enabled: boolean): void;
}
The Background
The theme's chart.background colours each pane. surfaceConfig runs on each pane's SciChart surface as it is created, after the theme, for anything else SciChart can do to a surface:
surfaceConfig: async ({ sciChartSurface }) => {
sciChartSurface.background = "transparent"; // show the page behind the chart
},
A background set here is yours: a theme switch leaves it alone.
Drawings
Drawing tools with a colour of their own keep it, like the orange horizontal line or the coloured pattern presets. Everything else a drawing would otherwise draw in white or in SciChart's dark defaults comes from theme.drawing:
- the line, for tools that set none (channel, poly line, extended line, angle line);
- neutral fills;
- label text, for labels without their own colour (Fibonacci levels in single-colour mode);
- the drag grips' outline and fill;
- the selection outline.
The chart applies these as drawings are placed or restored from a save, and moves them on setTheme. A colour set in a drawing's editor is kept.
The theme’s drawing colours set them; see Creating a Custom Theme.
The Order Book Heatmap
Each heatmap colour scale (Liquidity, Inferno, Viridis, Greyscale) has two ramps, one for dark backgrounds and one for light, and the heatmap draws whichever suits the chart's theme (isDark):
- On dark, thin liquidity fades into the background and walls glow bright.
- On light, the ramp runs the other way, from near-transparent pale to dark. Liquidity's walls are deep navy.
A theme switch redraws the current scale in the new ramp without reloading anything. studies.OrderBookHeatmap.palette sets the scale a theme starts with. A scale the user picks in the settings is kept for the theme it was picked in, like study colours. A custom ramp is kept as the user made it.
Where to read next
- Creating a Custom Theme: your own candle and indicator colours for every chart.
- Styling the UI Components: the toolbars and market depth ladder around the chart.
- SciFinanceChart: pane sizes and the rest of the chart's layout.