SharePointVault ~/gotchas/spfx ⌕ Search 404 pages, error messages, scripts…Ctrl K ★ Star
M↓ README.mdM↓ mermaid-text-clipping-webfont.md
sharepoint-vault›gotchas›spfx›mermaid-text-clipping-webfont.mdhistoryedit on GitHub
● GOTCHAspfx· 2 min read

Mermaid clips node text when you set a web font (measure-before-load)

applies to: SharePoint Online (SPFx, React 17); any web app rendering Mermaid client-sidereviewed: 2026-07-19#spfx#mermaid#fonts#rendering

Mermaid sizes each node box by measuring text at render time, so a not-yet-loaded web font measures narrow and clips the label after FOUT — give Mermaid a system font (keep your brand colours) or gate the render on document.fonts.ready.

Mermaid velikost každého uzlu počítá měřením textu při renderu, takže ještě nenačtený web font změří moc úzce a po FOUT ořízne popisek – dej Mermaidu systémový font (brand barvy nech), nebo render podmiň document.fonts.ready.

Symptom

You render Mermaid diagrams client-side and style them with a brand web font (via themeVariables.fontFamily and/or the top-level fontFamily). Node boxes come out too narrow — the last few characters of a label are cut off at the box border (e.g. Return request to employ instead of …employee). It looks fine with Mermaid's default font.

Cause

Mermaid measures text width at render time to size each node box, then draws the label. If the web font you asked for is not yet loaded when mermaid.render() runs, the browser measures with a fallback font (narrower), Mermaid sizes the box for that width — and once the web font finishes loading (FOUT), the actual text reflows wider than the box that was already committed. The box was cut for the wrong font.

This bites SPFx especially: brand fonts are usually injected via a runtime <link> in the page <head>, so the first diagram often renders before the font is ready.

Fix

Use a system font for Mermaid — both the top-level fontFamily and themeVariables.fontFamily. It is always available, so measurement and rendering agree:

const FONT = "'Segoe UI', system-ui, -apple-system, Arial, sans-serif";
mermaid.initialize({
  startOnLoad: false,
  securityLevel: 'strict',            // sanitizes untrusted diagram source (Mermaid runs it through DOMPurify)
  theme: 'base',
  fontFamily: FONT,
  themeVariables: { fontFamily: FONT /* + your brand colours: primaryColor, lineColor, … */ },
  flowchart: { htmlLabels: true, padding: 10 }
});

Keep your brand colours via themeVariables (primaryColor / primaryBorderColor / lineColor / …) — only the font needs to be a safe system stack; the palette can stay on-brand.

If you truly must use a web font, gate the first render behind document.fonts.ready (and re-render on font load) so measurement happens after the font is available. The system-font route is simpler and sidesteps the race entirely.

Related

  • Lazy-load Mermaid as its own chunk — await import(/* webpackChunkName: "mermaid" */ 'mermaid') — it is large and pulls in d3/dagre, so you don't want it in the main bundle.
  • Render only a complete fenced ```mermaid block. A half-streamed block (no closing fence yet) is invalid syntax and will flash the error/fallback state on every streaming delta; treat "closing fence not seen" as "still a code block".
  • securityLevel: 'strict' matters when the diagram source is untrusted (e.g. produced by an LLM) — it disables interactive/script features and sanitizes the output SVG.
Was this helpful?ask or add your experience on GitHub →
Saved you an hour? A star on GitHub helps other SharePoint people find the vault.★ Star on GitHub
last reviewed: 2026-07-19last updated: 2026-09-24historyedit on GitHubview source