How to Use themeCSS and themeVariables to Override Default Themes in Mermaid
The themeCSS and themeVariables configuration options provide complementary mechanisms for customizing Mermaid.js diagrams—themeVariables overrides design tokens like colors and fonts, while themeCSS injects raw CSS to target specific SVG elements after theme generation.
The mermaid-js/mermaid library generates diagrams as SVG with calculated styles based on selected themes. By leveraging these two configuration options in mermaid.initialize() or in-diagram directives, you can override default themes without maintaining a fork of the repository.
Understanding the themeCSS Configuration Option
themeCSS is a raw CSS string appended to the diagram's <style> block before generated theme styles are added. In packages/mermaid/src/mermaidAPI.ts, the createCssStyles function concatenates this value exactly as written:
// mermaidAPI.ts → createCssStyles
if (config.themeCSS !== undefined) {
cssStyles += `\n${config.themeCSS}`;
}
Because the CSS is injected exactly as-written, you can target any SVG selector that exists in the rendered output, such as .node rect, .edgePath, or foreignObject. This allows you to override specific visual properties that the theme generates, or add effects like drop shadows and custom borders that are not part of the standard design tokens.
Understanding the themeVariables Configuration Option
themeVariables is an object of design-token values—including colors, fonts, and sizes—that each built-in theme consumes to calculate its full stylesheet. The default configuration in packages/mermaid/src/defaultConfig.ts establishes the base values:
// defaultConfig.ts
themeVariables: theme.default.getThemeVariables(),
The type definition in packages/mermaid/src/config.type.ts clarifies the relationship between the two options, noting that you may use themeCSS to override values set by themeVariables.
During initialization in mermaidAPI.ts, the library merges your overrides with the selected theme:
// mermaidAPI.ts → initialize
if (options?.theme && options.theme in theme) {
// merge user overrides with the selected theme
options.themeVariables = theme[options.theme].getThemeVariables(options.themeVariables);
} else {
// fall back to the default theme
options.themeVariables = theme.default.getThemeVariables(options.themeVariables);
}
Each theme file (e.g., packages/mermaid/src/themes/theme-default.js) exports a getThemeVariables function that instantiates a Theme class, applies your overrides, and derives calculated values such as color scales and border contrasts.
How themeCSS and themeVariables Interact
The two options operate in sequence during the rendering pipeline:
themeVariablesdetermines the computed design tokens (e.g.,nodeBkg,edgeLabelBackground,fontFamily) used by the theme's generator.themeCSSis concatenated after those computed styles, enabling fine-tuning or forced overrides of any rule the theme generated.
The final CSS assembly occurs in packages/mermaid/src/styles.ts, called from mermaidAPI.ts:
const allStyles = getStyles(graphType, userCSSstyles, config.themeVariables);
Here, userCSSstyles already contains the raw themeCSS string injected during the createCssStyles phase.
Practical Implementation Examples
Override Colors and Fonts with themeVariables
Use themeVariables to modify specific design tokens while preserving the overall theme structure:
mermaid.initialize({
theme: 'forest',
themeVariables: {
// Override node appearance
nodeBkg: '#ffeb3b',
nodeBorder: '#f57f17',
// Typography adjustments
fontFamily: '"Helvetica Neue", Arial, sans-serif',
fontSize: '14px',
},
});
This example maintains the forest theme's edge styling and layout while forcing nodes to display with a bright yellow background.
Target Specific Elements with themeCSS
Use themeCSS when you need selector-level control that design tokens cannot provide:
mermaid.initialize({
theme: 'default',
themeCSS: `
/* Thick red edges */
.edgePath path { stroke: #e53935; stroke-width: 3px; }
/* Subtle shadow on nodes */
.node rect { filter: drop-shadow(2px 2px 2px rgba(0,0,0,0.2)); }
`,
});
Since themeCSS is injected after the default stylesheet, you do not need !important declarations unless overriding inline styles set by the theme renderer.
Combining Both for Complete Customization
For comprehensive theming, start with a base theme and layer both options:
mermaid.initialize({
theme: 'dark',
themeVariables: {
background: '#2e2e2e',
fontFamily: '"Fira Code", monospace',
},
themeCSS: `
.node text { text-transform: uppercase; }
.marker { fill: #ffeb3b; stroke: #ffeb3b; }
`,
});
This approach uses themeVariables to adjust the dark theme's foundational tokens while themeCSS handles text transformation and arrowhead colors that are not exposed as variables.
Using In-Diagram Directives
Mermaid also supports configuration via directives within the diagram syntax itself, parsed by packages/mermaid/src/utils/sanitizeDirective.ts:
%%{init: {
"theme": "base",
"themeVariables": { "nodeBkg": "#e0f7fa", "fontFamily": "Arial" },
"themeCSS": ".node rect { stroke-dasharray: 5,5; }"
}}%%
graph TD
A --> B
These directives populate config.themeCSS and config.themeVariables identically to JavaScript initialization.
Key Source Files in the Theming Architecture
Understanding the following files in the mermaid-js/mermaid repository clarifies how these configuration options flow through the system:
packages/mermaid/src/defaultConfig.ts- Supplies defaultthemeVariablesandthemeCSSentries in the base configuration object.packages/mermaid/src/config.type.ts- Declares the TypeScript interfaces forthemeCSSandthemeVariables, documenting their intended use.packages/mermaid/src/mermaidAPI.ts- Central hub where options are merged,themeVariablesare resolved via the selected theme'sgetThemeVariablesfunction, andthemeCSSis concatenated into the final stylesheet.packages/mermaid/src/themes/index.js- Maps theme names (default,forest,dark,base) to their respectivegetThemeVariablesimplementations.packages/mermaid/src/themes/theme-default.js(and sibling theme files) - ImplementsgetThemeVariablesto build Theme class instances, apply user overrides, and calculate derived values.packages/mermaid/src/styles.ts- Receives processedthemeVariablesand rawthemeCSS(asuserStyles) to assemble the final CSS string injected into the SVG.packages/mermaid/src/utils/sanitizeDirective.ts- Parses in-diagraminitdirectives, enablingthemeCSSandthemeVariablesconfiguration within Markdown code blocks.
Summary
themeVariablesoverrides design tokens (colors, fonts, sizes) at the theme level before CSS generation.themeCSSinjects raw CSS after theme styles are calculated, enabling selector-level customization of SVG elements.- Initialization flow: User options merge with theme defaults in
mermaidAPI.ts, thenstyles.tsassembles the final stylesheet. - Directive support: Both options work within
%%{init: {...}%%blocks for configuration without JavaScript.
Frequently Asked Questions
What is the difference between themeCSS and themeVariables in Mermaid.js?
themeVariables is an object of design tokens that modifies how the theme calculates its base styles, affecting properties like nodeBkg and fontFamily before CSS is generated. themeCSS is a raw CSS string appended after theme generation, allowing you to target specific SVG selectors like .node rect or .edgePath that may not be exposed as variables.
Can I use themeCSS to override any SVG element in Mermaid diagrams?
Yes. Because themeCSS is injected directly into the diagram's <style> block as implemented in packages/mermaid/src/mermaidAPI.ts, you can write CSS rules targeting any valid SVG selector rendered by Mermaid, including .node, .edgeLabel, foreignObject, and specific marker elements.
How do I dynamically change themes after initialization using themeVariables?
While mermaid.initialize() sets the base configuration, you can render diagrams with different themeVariables by passing a configuration object to mermaid.render() or by using in-diagram %%{init: ...}%% directives. Each render call processes the provided themeVariables fresh through the selected theme's getThemeVariables function.
Is it possible to use themeCSS and themeVariables in Markdown environments?
Yes. Both options are supported through the init directive syntax within the diagram definition itself, parsed by packages/mermaid/src/utils/sanitizeDirective.ts. This allows you to customize themes in static site generators and Markdown documentation without requiring a JavaScript initialization block.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →