mermaid-embed
v0.1.0
Published
Embeddable Mermaid widget with Shadow DOM CSS isolation
Downloads
132
Maintainers
Readme
mermaid-embed
A ~2.8 kB drop-in widget that renders Mermaid diagrams on any webpage — with Shadow DOM CSS isolation, scoped custom themes, and zero framework lock-in.
🔗 Live demo & docs: https://suniltaneja.github.io/mermaid-embed/
Why
- Tiny — ~2.8 kB / ~1.4 kB gzip. Mermaid itself loads from CDN on demand, so it never bloats your initial page load.
- Shadow DOM scoped — Custom CSS targets only the diagram. Your page styles can't leak in, the diagram can't leak out. No
!importantwars. - Drop in, done — One script tag, mark any element with
.mermaid-embed, write Mermaid. Works with React, Vue, Astro, Next, plain HTML — any stack.
Install
CDN (recommended for static pages)
<script src="https://unpkg.com/mermaid-embed@latest/dist/mermaid-embed.iife.js"></script>Or pin a version:
<script src="https://unpkg.com/[email protected]/dist/mermaid-embed.iife.js"></script>jsDelivr also works:
<script src="https://cdn.jsdelivr.net/npm/mermaid-embed@latest/dist/mermaid-embed.iife.js"></script>npm
npm install mermaid-embedimport { render, autoInit } from 'mermaid-embed';Quick start
The widget auto-initialises on DOMContentLoaded — any element with class .mermaid-embed gets rendered.
Inline diagram
<script src="https://unpkg.com/mermaid-embed@latest/dist/mermaid-embed.iife.js"></script>
<div class="mermaid-embed">
<script type="text/mermaid">
graph TD
A[User] --> B{Logged in?}
B -- Yes --> C[Dashboard]
B -- No --> D[Login]
</script>
</div>With custom CSS
<div class="mermaid-embed" data-css="
.node rect { fill: #fdf2f8 !important; stroke: #ec4899 !important; }
.edgePath .path { stroke: #a855f7 !important; }
.nodeLabel { color: #831843 !important; }
">
<script type="text/mermaid">
flowchart LR
Idea --> Draft --> Review --> Ship
</script>
</div>Programmatic
import { render } from 'mermaid-embed';
await render('#diagram', 'graph TD; A --> B', '.node rect { fill: #eef; }');How to pass the Mermaid source
In order of precedence, the widget reads diagram source from:
- A child
<script type="text/mermaid">block (recommended — preserves whitespace) - A child
<template>element - A
data-mermaidattribute - The element's plain
textContent
<!-- 1. Script block -->
<div class="mermaid-embed">
<script type="text/mermaid">
graph TD; A --> B
</script>
</div>
<!-- 2. Template -->
<div class="mermaid-embed">
<template>graph TD; A --> B</template>
</div>
<!-- 3. Data attribute -->
<div class="mermaid-embed" data-mermaid="graph TD; A --> B"></div>How to pass custom CSS
Two equivalent ways:
<!-- 1. data-css attribute (good for one-liners) -->
<div class="mermaid-embed" data-css=".node rect { fill: pink; }">
<script type="text/mermaid">graph TD; A --> B</script>
</div>
<!-- 2. Inline style block (good for multi-line) -->
<div class="mermaid-embed">
<style data-embed-css>
.node rect { fill: pink; }
.edgePath .path { stroke: hotpink; }
</style>
<script type="text/mermaid">graph TD; A --> B</script>
</div>All of this CSS is injected into the widget's Shadow DOM, so it only applies to your diagram — never to the host page, and never affected by it.
Common Mermaid SVG selectors
| Selector | What it styles |
| --- | --- |
| .node rect, .node polygon, .node circle, .node ellipse | Node shapes |
| .edgePath .path | Edge lines |
| .arrowheadPath | Arrowheads |
| .nodeLabel | Node text |
| .edgeLabel | Edge text |
| .cluster rect | Subgraph containers |
API
import { render, autoInit, loadMermaid } from 'mermaid-embed';render(target, markdown, customCss?): Promise<void>
Renders Mermaid markdown into target (a CSS selector or HTMLElement). Optional customCss is injected into the Shadow DOM.
await render('#diagram', 'graph TD; A --> B');
await render(document.getElementById('d')!, 'graph TD; A --> B', '.node rect { fill: pink; }');autoInit(root?: ParentNode): void
Scans root (default: document) for .mermaid-embed elements that haven't been initialised yet and renders each. Useful after dynamically inserting new diagrams.
autoInit(); // scan the whole document
autoInit(myContainer); // scan inside one containerloadMermaid(): Promise<Mermaid>
Returns the Mermaid module loaded from CDN. Lazily loaded — only fetched the first time it's needed. Subsequent calls return the cached instance.
Window global
When loaded via <script> tag, the same API is available as window.MermaidEmbed:
<script>
await window.MermaidEmbed.render('#d', 'graph TD; A --> B');
</script>Bundles
| File | Format | When to use |
| --- | --- | --- |
| dist/mermaid-embed.js | ESM | import in bundlers / modern browsers |
| dist/mermaid-embed.umd.cjs | UMD | require() in CommonJS environments |
| dist/mermaid-embed.iife.js | IIFE | Direct <script> tag, sets window.MermaidEmbed |
| dist/mermaid-embed.d.ts | Types | TypeScript declarations |
Each is ~2.8 kB raw, ~1.4 kB gzip. Sourcemaps are shipped alongside.
Develop
npm install
npm run dev # marketing/demo page at http://localhost:5173
npm run build # library build → dist/
npm run build:site # site build → dist-site/
npm run typecheck # tsc --noEmitLicense
MIT © Sunil Taneja
Attribution
mermaid-embed is an independent open-source project and is not affiliated with or endorsed by the Mermaid project. Mermaid is loaded at runtime from a public CDN under its own MIT license.
