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:

  1. themeVariables determines the computed design tokens (e.g., nodeBkg, edgeLabelBackground, fontFamily) used by the theme's generator.
  2. themeCSS is 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:

Summary

  • themeVariables overrides design tokens (colors, fonts, sizes) at the theme level before CSS generation.
  • themeCSS injects 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, then styles.ts assembles 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →