Overview

<mermaid-element> brings the declarative simplicity of HTML to diagramming. Instead of manually configuring Mermaid, managing initialization lifecycles, or wrangling script tags, you simply write your Mermaid syntax inside a <mermaid-element> tag and let the browser render it.

Live Demonstration Declarative HTML
graph LR HTML[Raw HTML Syntax] --> Element[<mermaid-element> Custom Element] Element --> Engine[Mermaid 12 via jsDelivr CDN] Engine --> SVG[Rendered SVG in Shadow DOM]
<mermaid-element>
    graph LR
        HTML[Raw HTML Syntax] --> Element[&lt;mermaid-element&gt; Custom Element]
        Element --> Engine[Mermaid 12 via jsDelivr CDN]
        Engine --> SVG[Rendered SVG in Shadow DOM]
    </mermaid-element>

Features

Engineered as a modern, standalone web component for effortless documentation, dashboards, blogs, and interactive tools.

⚡ Zero-Config & Declarative

Place raw Mermaid syntax directly inside the custom element. No manual JavaScript initialization calls required.

📦 Zero Dependencies

Ships as an ultra-lightweight package. Dynamically loads Mermaid 12 from jsDelivr on demand without bloating your app bundle.

🔄 Dynamic Version Switching

Need a specific release? Pass mermaid="10.9.8" or a custom endpoint URL to fetch and render with that exact version.

🔌 Pre-Installed / Bundled Support

Have Mermaid already in your bundle? Set MermaidElement.defaultMermaid = mermaid to use your pre-installed package offline.

🧠 Smart In-Memory Caching

Instances share loaded modules and in-flight promises. Multiple diagrams on the same page will only fetch Mermaid once.

🛡️ Shadow DOM & CSS Parts

Diagram SVGs render in open Shadow Roots to prevent style bleeding. Customize styling using standard CSS ::part() hooks.

Installation & Setup

Install via npm for modern bundlers, or drop in a script tag from a CDN.

1. Using npm (Standalone / Dynamic Loading) Zero Dependencies

Install mermaid-element alone. It will dynamically fetch Mermaid 12 on demand without bloating your node_modules:

npm install mermaid-element
import 'mermaid-element'; // Automatically registers <mermaid-element>
2. Using npm with Pre-Installed / Bundled Mermaid Offline / Self-Contained

If your application bundles Mermaid locally or runs in an air-gapped environment, install both packages and assign your instance:

npm install mermaid-element mermaid
import mermaid from 'mermaid';
    import { MermaidElement } from 'mermaid-element';
    
    // Direct <mermaid-element> to use your local bundled Mermaid library
    MermaidElement.defaultMermaid = mermaid;
3. Using a CDN (No Build Tools Required) Vanilla HTML

Include the module directly in any HTML document without build tools:

<script type="module" src="https://cdn.jsdelivr.net/npm/mermaid-element/index.js"></script>

Controlling Mermaid Version

How <mermaid-element> resolves and loads Mermaid libraries.

By default, <mermaid-element> dynamically loads Mermaid 12 on demand from jsDelivr (see Example 1).

Authors can override this per element using the mermaid attribute:

  • Version String: Pass a release version like mermaid="10.9.8" to fetch that release on demand from the CDN (see Example 2).
  • Full URL or Path: Pass a full URL or relative path like mermaid="https://.../mermaid.esm.min.mjs" to load from a custom endpoint or self-hosted asset (see Example 3).
Bring Your Own Mermaid MermaidElement.defaultMermaid

If your application already bundles Mermaid or operates in an offline / air-gapped environment, you can supply your own default instance instead of fetching from a CDN:

import mermaid from 'mermaid';
import { MermaidElement } from 'mermaid-element';

// Use your pre-installed or pre-configured instance as the default
MermaidElement.defaultMermaid = mermaid;

For script-based setups, <mermaid-element> also automatically detects a globally defined window.mermaid. Individual elements can still override this default by specifying their own mermaid attribute.

🧠 Smart In-Memory Caching

Loaded Mermaid modules and pending load promises are cached in memory by URL. When multiple <mermaid-element> elements share the same version or endpoint on a page, Mermaid is fetched and initialized only once.

Styling Before Upgrade

Before custom elements are registered and upgraded by the browser, they behave like unstyled inline text elements. Because scripts take time to download and execute, you can choose between two strategies for how un-upgraded <mermaid-element> elements appear while loading:

Option 1: Fallback Styling (Show Mermaid Code) Results in a FOUC

Format the raw Mermaid syntax as a readable monospace code block until the component upgrades:

mermaid-element:not(:defined) {
  display: block;
  white-space: pre-wrap;
  font-family: monospace;
}

Trade-off: Flash of Unstyled Content (FOUC)

The diagram definition is immediately legible while scripts load, but this results in a Flash of Unstyled Content (FOUC): once the custom element registers and Mermaid renders, the raw text abruptly transforms into the rendered SVG diagram.

Simulated Pre-Upgrade Appearance Before Script Execution
graph TD Client[Browser] -->|Request| Server[Node.js] Server -->|Response| Client
Option 2: Hide Until Defined Results in a CLS

Hide <mermaid-element> elements completely until they are registered in the CustomElementRegistry:

mermaid-element:not(:defined) {
  display: none;
}

Trade-off: Cumulative Layout Shift (CLS)

This completely prevents any flash of raw Mermaid code or unstyled text (no FOUC), but results in a Cumulative Layout Shift (CLS): when the custom element upgrades, the diagram suddenly appears in the document flow and shifts subsequent content downward.

JavaScript API

Full programmatic control over diagram definitions, themes, versions, and lifecycle events.

Properties & Attributes DOM API
Property / Attribute Type Description
diagram string Gets or sets the raw Mermaid syntax. Setting this property triggers an automatic re-render.
mermaid string | null Gets or sets the mermaid attribute (version string, URL, or null to default to Mermaid 12).
theme string | null Gets or sets the theme attribute (default, neutral, dark, forest, base).
svg SVGSVGElement | null Read-only reference to the rendered SVG element inside the shadow root.
MermaidElement.defaultMermaid any Static property to specify an explicit pre-configured Mermaid instance to use as the default.
Methods & Events Events
Member Signature / Detail Description
render() Promise<{ svg, diagram } | null> Method to manually trigger a diagram re-render.
@render { detail: { svg: string, diagram: string } } Event dispatched when the diagram renders successfully into the Shadow Root.
@error { detail: { error: Error, diagram: string } } Event dispatched when a syntax or rendering error occurs.
CSS Shadow Parts ::part()

<mermaid-element> exposes internal structural elements via the part attribute so you can style them from your page stylesheet using ::part():

Part Name Element Description
container <div class="container"> The flex container wrapping the rendered SVG inside the Shadow Root.
error <div class="error"> The alert notification container rendered when a syntax error occurs.
/* Style the diagram container */
mermaid-element::part(container) {
  padding: 1.5rem;
  background: var(--bg-surface-elevated);
  border-radius: 8px;
}

/* Customize the error box */
mermaid-element::part(error) {
  border-color: #ef4444;
  background-color: #fef2f2;
}

Example 1: Default (Mermaid 12)

When no mermaid attribute is passed, <mermaid-element> uses your configured MermaidElement.defaultMermaid (or window.mermaid) if provided, or defaults to Mermaid 12 dynamically loaded on demand from jsDelivr.

Architecture Flowchart <mermaid-element>
graph TD subgraph Frontend [Client Tier] Web[Web Browser] Mobile[Mobile App] end subgraph Backend [Server Infrastructure] LB[Load Balancer] API1[API Server 1] API2[API Server 2] end subgraph Storage [Database Tier] DB[(Primary Database)] Cache[(Redis Cache)] end Web --> LB Mobile --> LB LB --> API1 LB --> API2 API1 --> DB API2 --> DB API1 --> Cache API2 --> Cache
<mermaid-element>
graph TD
    subgraph Frontend [Client Tier]
        Web[Web Browser]
        Mobile[Mobile App]
    end
    ...
</mermaid-element>

Example 2: Dynamic Version (CDN)

Pass a version string or number in the mermaid attribute (e.g. 10.9.8) to dynamically load that version on-demand from cdn.jsdelivr.net.

Sequence Diagram loaded with Mermaid v10.9.8 mermaid="10.9.8"
sequenceDiagram autonumber actor Customer actor Cashier participant Inventory participant PaymentGateway Customer->>Cashier: Hands items to purchase Cashier->>Inventory: Scan barcodes Inventory-->>Cashier: Price & stock confirmed Cashier->>Customer: Request payment Customer->>PaymentGateway: Tap credit card PaymentGateway-->>Customer: Transaction approved Cashier-->>Customer: Receipt issued
<mermaid-element mermaid="10.9.8">
sequenceDiagram
    autonumber
    actor Customer
    actor Cashier
    ...
</mermaid-element>

Example 3: Dynamic Version from URL

If the mermaid attribute starts with https://, http://, or a relative path, it will be loaded directly from that exact URL.

State Diagram loaded from specific URL mermaid="https://cdn.jsdelivr.net/npm/mermaid@11.4.1/..."
stateDiagram-v2 [*] --> Draft Draft --> InReview : Submit for Review InReview --> Approved : Approve InReview --> Draft : Request Changes Approved --> Published : Deploy Published --> [*]
<mermaid-element mermaid="https://cdn.jsdelivr.net/npm/mermaid@11.4.1/dist/mermaid.esm.min.mjs">
stateDiagram-v2
    [*] --> Draft
    ...
</mermaid-element>

Interactive Live Playground

Test diagram types, edit Mermaid syntax live, switch versions, and observe dynamic updates.

Status: Ready Render time: 0 ms
Live Preview <mermaid-element>
graph TD A[Client Request] --> B[API Gateway] B --> C{Authentication} C -->|Valid| D[Microservice] C -->|Invalid| E[401 Unauthorized] D --> F[(PostgreSQL)] D --> G[(Redis Cache)]
<mermaid-element>
graph TD
    A[Client Request] --> B[API Gateway]
    B --> C{Authentication}
    ...
</mermaid-element>

Example 5: Error Handling

When invalid Mermaid syntax is provided, <mermaid-element> captures the parse error gracefully and renders an accessible error notification with part="error" without crashing the application.

Diagram with syntax error Graceful Error State
invalid diagram syntax this should trigger the error boundary

Example 6: Using <template> for Unescaped Syntax

To avoid browser HTML entity escaping when using special characters like <, >, or HTML node labels, you can wrap your Mermaid definition inside a <template> tag.

Template Tag Example <template>
<mermaid-element>
  <template>
flowchart LR
    A["Raw & Unescaped <b>HTML</b>"] --> B["<tag>Node B</tag>"]
    B --> C["Node C"]
  </template>
</mermaid-element>

Example 7: CSS Shadow Parts (::part)

Use CSS ::part(container) to style the wrapper inside the element's Shadow DOM directly from your page stylesheet.

Custom Container Styling via ::part(container) ::part(container)
graph LR Client[Browser Client] --> LB[Load Balancer] LB --> App1[App Server 1] LB --> App2[App Server 2]
/* Page CSS */
mermaid-element.styled-part-example::part(container) {
  padding: 1.5rem;
  background: var(--bg-surface-elevated);
  border: 2px dashed var(--primary-color);
  border-radius: 10px;
}
<mermaid-element class="styled-part-example">
graph LR
    Client[Browser Client] --> LB[Load Balancer]
    LB --> App1[App Server 1]
    LB --> App2[App Server 2]
</mermaid-element>