The CSS Stylesheet
The chart is drawn with WebGL, but everything around it is HTML: the pane control bars and dividers, the toolbars, the drawing tools, the study forms and the loading states. That HTML gets its look from one stylesheet, scitrader.css, and you restyle it with ordinary CSS.
Importing the Stylesheet
Import it once, e.g. in your app's entry file:
import "scichart-scitrader/scitrader.css";
It is plain CSS: nothing in the SDK imports it, so it works with any bundler, or as a <link>. Without it, the controls still work, but look like plain browser buttons. The components set inline only the layout they need to work, such as positions and sizes while dragging; colours, borders, spacing, fonts and hover states all come from the stylesheet.
The Theme's CSS Variables
The stylesheet takes its colours from the theme, through CSS variables. Each theme colour has one, named --st-<group>-<name>: ui.textMuted is --st-ui-text-muted, chart.loadingTint is --st-chart-loading-tint. Every rule gives a fallback, the dark theme's colour, so a control outside any theme still looks right: var(--st-ui-text, #ffffff).
Where the variables come from:
| Writes the variables on | |
|---|---|
Sci, < | The chart's container, for its pane controls, dividers and loading states |
Market, < | The panel's element |
Sci (React) | A wrapper element, and : |
apply | Any element you choose: use it for controls outside the chart in plain TypeScript |
The chart and the depth panel write the variables on their own elements, so a variable you set on a parent, e.g. .my-app { --st-ui-accent: orange }, is overridden for everything inside them. To change a variable inside the chart, set it on the elements themselves: .my-app .st-pane-control-bar { --st-ui-accent: orange }. The example's "Theme variables" skin does both.
Use the variables in your own CSS, so your controls follow the theme too:
.my-panel {
background: var(--st-ui-panel, #262334);
color: var(--st-ui-text-muted, #9da2bc);
}
themeToCssVariables(theme) lists every variable and its value. Study colours aren't among them: studies are drawn by WebGL, and get their colours from the theme directly.
Overriding the Stylesheet
Override its rules in your own CSS, loaded after scitrader.css. Every element has a class, listed below:
/* Round drawing tools */
.my-chart .st-drawing-toolbar__button {
border-radius: 50%;
}
/* A thicker highlight on the drawing tool in use */
.my-chart .st-drawing-toolbar__button[aria-pressed="true"] {
border-width: 2px;
}
- Scope your rules under a class of your own, such as
.my-charthere. It keeps them to one chart, and makes each rule more specific than the one it replaces, so it wins whichever stylesheet loads first. - A rule with
:not()needs the same:not(). Somescitrader.cssrules have one, such as the divider's hover,:hover:not([data-dragging="true"]). Repeat it in yours to stay more specific. - States are attributes, not classes. Style
:hover,:disabled,aria-pressedon toggles and on the selected button of a group,aria-checkedon menu items,aria-expandedon a study list's open card,aria-disabled, anddata-dragging="true"on a divider being dragged. - Translucent hovers and lines use
rgb(var(--st-ui-overlay-rgb) / alpha). The overlay colour is white on dark themes and black on light ones, so the same rule works on both. - The crosshair isn't HTML. It is drawn with the chart, so its colours come from the theme's
chartgroup; see Styling the Chart.
TypeScript Example: Restyling the Controls with CSS
A BTC-USD chart with the drawing tools rail, zoom buttons on each pane, and a control bar when you hover a pane. Each button above the chart puts a different set of CSS rules on the page: rounded, square and flat, or new values for the theme’s CSS variables. Pick a drawing tool, or hover a pane, to see each skin’s states.
The code for this example is found below.
- TS
import "scichart-scitrader/scitrader.css";
import { SciChartSurface } from "scichart";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
DrawingToolbar,
DrawingToolsController,
idbPriceStore,
OHLCStudy,
OnChartButtonsModifier,
RSIStudy,
SciFinanceChartPanel,
VolumeStudy,
} from "scichart-scitrader";
// This example expects this HTML:
// <div style="display: flex; flex-direction: column; height: 100%">
// <div id="skins"></div>
// <div id="skinned" style="display: flex; flex: 1; min-height: 0">
// <div id="tools"></div>
// <div id="chart" style="flex: 1; min-width: 0"></div>
// </div>
// </div>
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
// CSS overrides for the SDK's controls. In an app, these rules go in your own stylesheet, loaded
// after scitrader.css. Each skin is scoped under a class on an element around the chart, which keeps
// it to this chart and makes each rule more specific than the scitrader.css rule it replaces
const SKINS: Array<{ name: string; css: string }> = [
{ name: "Default", css: "/* No overrides: scitrader.css alone */" },
{
name: "Rounded",
css: `
/* Round drawing tools */
.skin .st-drawing-toolbar__button { border-radius: 50%; }
/* Pill-shaped zoom buttons and pane control bars */
.skin .st-on-chart-buttons,
.skin .st-pane-control-bar { border-radius: 999px; padding-left: 8px; padding-right: 8px; }
.skin .st-pane-control-bar__button,
.skin .st-on-chart-buttons__button { border-radius: 50%; }`,
},
{
name: "Square and flat",
css: `
/* Square corners, and no borders on idle buttons */
.skin .st-drawing-toolbar__button,
.skin .st-on-chart-buttons,
.skin .st-on-chart-buttons__button,
.skin .st-pane-control-bar,
.skin .st-pane-control-bar__button { border-radius: 0; }
.skin .st-drawing-toolbar__button:not([aria-pressed="true"]) { border-color: transparent; }`,
},
{
name: "Theme variables",
css: `
/* Change the theme's colours for these controls only, through its CSS variables.
The drawing toolbar is outside the chart, so it reads them from any parent: */
.skin {
--st-ui-menu-background: #1f1a12;
--st-ui-selection: #f59e0b;
}
/* The chart writes the theme's variables on its own container, which wins over a parent.
To reach controls inside the chart, set the variables on them: */
.skin .st-pane-control-bar,
.skin .st-on-chart-buttons {
--st-ui-toolbar-background: #1f1a12;
--st-ui-toolbar-active: #f59e0b;
--st-ui-icon: #f59e0b;
}`,
},
];
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",
studies: [new OHLCStudy(), new VolumeStudy(), new RSIStudy()],
});
const chart = financeChartPanel.financeApi;
// Controls to restyle: the drawing tools rail...
const drawing = DrawingToolsController.attach(chart);
DrawingToolbar.create(document.getElementById("tools"), drawing, { orientation: "vertical" });
// ...the zoom and pan buttons on every pane, shown all the time so their style is easy to see,
// and each pane's control bar: hover a pane to see it
const withButtons = new Set<SciChartSurface>();
const addButtons = () =>
chart.chartPanes.forEach(({ surface }) => {
if (surface && !withButtons.has(surface)) {
withButtons.add(surface);
surface.chartModifiers.add(new OnChartButtonsModifier({ visible: true }));
}
});
addButtons();
chart.paneConfigured.subscribe(addButtons); // panes added later, e.g. by a new study
// Switch skins: put the picked skin's rules in a <style> element
document.getElementById("skinned").classList.add("skin");
const style = document.head.appendChild(document.createElement("style"));
const bar = document.getElementById("skins");
Object.assign(bar.style, barStyle);
const render = (current: string) =>
bar.replaceChildren(
...SKINS.map((skin) => {
const button = document.createElement("button");
button.textContent = skin.name;
Object.assign(button.style, buttonStyle(skin.name === current));
button.onclick = () => {
style.textContent = skin.css;
render(skin.name);
};
return button;
})
);
render("Default");
// When the page goes away: drawing.detach(); financeChartPanel.cleanup();
return financeChartPanel;
}
// The skin buttons use the theme's CSS variables, with the dark theme's values as fallbacks
const barStyle: Partial<CSSStyleDeclaration> = {
display: "flex",
flexWrap: "wrap",
gap: "4px",
padding: "8px 12px",
background: "var(--st-ui-toolbar-background, #2b2839)",
borderBottom: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};
const buttonStyle = (selected: boolean): Partial<CSSStyleDeclaration> => ({
padding: "4px 12px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.15))",
borderRadius: "4px",
background: selected ? "var(--st-ui-accent, #5c5cff)" : "var(--st-ui-button-background, #363345)",
color: "var(--st-ui-text, #e8e8ee)",
font: "13px sans-serif",
cursor: "pointer",
});
createChart();
React Example: Restyling the Controls with CSS
The same in React: the rules go in a <style> element.
The code for this example is found below.
- React
import "scichart-scitrader/scitrader.css";
import * as React from "react";
import { SciChartSurface } from "scichart";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
ISciFinanceChartPanelApi,
ISciFinanceChartPanelConfig,
OHLCStudy,
OnChartButtonsModifier,
RSIStudy,
VolumeStudy,
} from "scichart-scitrader";
import { DrawingToolbar, SciFinanceChartView, useDrawingTools } from "scichart-scitrader-react";
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
// CSS overrides for the SDK's controls. In an app, these rules go in your own stylesheet, loaded
// after scitrader.css. Each skin is scoped under a class on an element around the chart, which keeps
// it to this chart and makes each rule more specific than the scitrader.css rule it replaces
const SKINS: Array<{ name: string; css: string }> = [
{ name: "Default", css: "/* No overrides: scitrader.css alone */" },
{
name: "Rounded",
css: `
/* Round drawing tools */
.skin .st-drawing-toolbar__button { border-radius: 50%; }
/* Pill-shaped zoom buttons and pane control bars */
.skin .st-on-chart-buttons,
.skin .st-pane-control-bar { border-radius: 999px; padding-left: 8px; padding-right: 8px; }
.skin .st-pane-control-bar__button,
.skin .st-on-chart-buttons__button { border-radius: 50%; }`,
},
{
name: "Square and flat",
css: `
/* Square corners, and no borders on idle buttons */
.skin .st-drawing-toolbar__button,
.skin .st-on-chart-buttons,
.skin .st-on-chart-buttons__button,
.skin .st-pane-control-bar,
.skin .st-pane-control-bar__button { border-radius: 0; }
.skin .st-drawing-toolbar__button:not([aria-pressed="true"]) { border-color: transparent; }`,
},
{
name: "Theme variables",
css: `
/* Change the theme's colours for these controls only, through its CSS variables.
The drawing toolbar is outside the chart, so it reads them from any parent: */
.skin {
--st-ui-menu-background: #1f1a12;
--st-ui-selection: #f59e0b;
}
/* The chart writes the theme's variables on its own container, which wins over a parent.
To reach controls inside the chart, set the variables on them: */
.skin .st-pane-control-bar,
.skin .st-on-chart-buttons {
--st-ui-toolbar-background: #1f1a12;
--st-ui-toolbar-active: #f59e0b;
--st-ui-icon: #f59e0b;
}`,
},
];
export function CssOverridesChart() {
const [skin, setSkin] = React.useState(SKINS[0]);
const [api, setApi] = React.useState<ISciFinanceChartPanelApi>();
const { controller } = useDrawingTools(api); // the drawing tools rail
// The zoom and pan buttons on every pane, shown all the time so their style is easy to see
React.useEffect(() => {
if (!api) return undefined;
const chart = api.financeApi;
const withButtons = new Set<SciChartSurface>();
const addButtons = () =>
chart.chartPanes.forEach(({ surface }) => {
if (surface && !withButtons.has(surface)) {
withButtons.add(surface);
surface.chartModifiers.add(new OnChartButtonsModifier({ visible: true }));
}
});
addButtons();
chart.paneConfigured.subscribe(addButtons); // panes added later, e.g. by a new study
return () => chart.paneConfigured.unsubscribe(addButtons);
}, [api]);
// 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",
studies: [new OHLCStudy(), new VolumeStudy(), new RSIStudy()],
}),
[]
);
return (
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
{/* The picked skin's rules. In an app, they would be in your stylesheet */}
<style>{skin.css}</style>
<div style={barStyle}>
{SKINS.map((s) => (
<button key={s.name} style={buttonStyle(s === skin)} onClick={() => setSkin(s)}>
{s.name}
</button>
))}
</div>
<div className="skin" style={{ display: "flex", flex: 1, minHeight: 0 }}>
<DrawingToolbar controller={controller} orientation="vertical" />
<div style={{ flex: 1, minWidth: 0 }}>
<SciFinanceChartView config={config} onInit={setApi} />
</div>
</div>
</div>
);
}
// The skin buttons use the theme's CSS variables, with the dark theme's values as fallbacks
const barStyle: React.CSSProperties = {
display: "flex",
flexWrap: "wrap",
gap: 4,
padding: "8px 12px",
background: "var(--st-ui-toolbar-background, #2b2839)",
borderBottom: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};
const buttonStyle = (selected: boolean): React.CSSProperties => ({
padding: "4px 12px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.15))",
borderRadius: 4,
background: selected ? "var(--st-ui-accent, #5c5cff)" : "var(--st-ui-button-background, #363345)",
color: "var(--st-ui-text, #e8e8ee)",
font: "13px sans-serif",
cursor: "pointer",
});
CSS Class Reference
| Component | Classes |
|---|---|
| Per-pane control bar | st-, _ (your content, Layout), _, _, _ |
| Control bar drawer (touch layout) | st-, _, _ |
| Divider between panes | st- (-), _ |
| Restore strip for hidden panes | st-, _, _ |
| A pane | st-, and st- while it has keyboard focus |
| Candle counter | st- |
| Pane loading: skeleton, switch overlay, progress dots | st- (_); st- (_); st-, _, _, _ |
| On-chart zoom / pan buttons | st-, _ |
| Annotation quick-edit toolbar | st-, _, _, _, _, _ |
| Drawing toolbar | st- (- / -), _, _, _, _, _ |
| Market depth panel (the ladder itself is canvas) | st-, _, _, _, _, _, _, _; the hover readout _ (- / -), _, _, _ |
| Loading overlays inside the chart | st-, st-, _ |
| Interval, period and live-tip buttons | st-, _, with st-, st- or st- on the group |
| Candle-type picker and its menu | st-, _, _; st-, _, _ |
| Study settings form | st-, _, _, _, _, _ |
| Study list | st-, _, _, _, _, _, _, _, _, _ |
| Form fields | st- (-, -), _, _, _, _; st-, _, _, _, _ |
| Colour field and its picker | st- (-), _, _, _, _; st-, _, _, _, _, _, _, _, … |
| Gradient editor | st-, _, _, _, _, _, _ |
| Drawings list | st-, _, _, _, _, _, _, _, _, _, _, _ |
| Confirmation dialog ("Clear all") | st-, _, _, _, _, _, _ |
CSS Variable API
themeToCssVariables, applyThemeCssVariables, cssVariableName, themeVar and uiVar, with their TSDoc
/**
* The theme as CSS custom properties, for everything drawn with HTML and CSS rather than WebGL:
* the vanilla SDK toolbars and overlays, and the React components' stylesheets.
*
* Names are `--st-<group>-<key>` in kebab case: `ui.textMuted` becomes `--st-ui-text-muted`,
* `chart.loadingTint` becomes `--st-chart-loading-tint`. Study colours are not included; they are
* drawn by WebGL and are applied to the studies directly.
*
* Stylesheets should always give a fallback, `var(--st-ui-text, #ffffff)`, so a component still
* renders outside a themed container.
*/
function themeToCssVariables(theme: ISciTraderTheme): Record<string, string>;
/** `cssVariableName("ui", "textMuted")` → `"--st-ui-text-muted"`. */
function cssVariableName(group: string, key: string): string;
/** Write the theme's CSS variables onto an element, so it and its descendants pick them up. */
function applyThemeCssVariables(element: HTMLElement, theme: ISciTraderTheme): void;
/** `var(--st-ui-text, #ffffff)`: a CSS reference to one theme colour, falling back to its value in `theme`. */
function themeVar(theme: ISciTraderTheme, group: "chart" | "candles" | "market" | "ui", key: string): string;
function uiVar(key: keyof ISciTraderUiColors): string;
Where to read next
- Creating a Custom Theme: change the colours everywhere, not only in CSS.
- Styling the UI Components: toolbars and the market depth ladder.
- Mobile and Responsive Styling: touch-sized controls in CSS.