How to Draw Block Diagrams in Mermaid
Block diagrams give you direct, manual control over a grid layout — useful when you want specific positioning that a flowchart's automatic layout won't give you. Mermaid uses the block-beta diagram type, built around a columns grid, space for gaps, and nested block:groupId:N ... end for composite structures.
Why Use Block Diagrams?
- Manual positioning — Place blocks in an exact grid, without relying on an auto-layout engine's choices
- Nested structures — Group related blocks visually with a composite container
- Simple, static layouts — Good for grid-like structures (network racks, module layouts) where the shape is fixed, not flow-driven
Use Cases
✅ Suitable:
- Small (≤10-15 blocks), mostly-flat grid layouts where you need exact positioning
- Simple network/module diagrams with a handful of connections between adjacent blocks
❌ Not suitable:
- Anything with many connections, especially connections that "skip over" a block in the grid — block-beta has no anchor points, so an edge is just a straight line between block centers, and it will cross through anything in between (see below)
- Deep nesting combined with column spans — this combination is where
block-betais least stable (see Limitations) - Anything rendered inside a React/SPA-based tool —
block-betahas a documented crash (Converting circular structure to JSON) that a major team (Vercel) hit in production and worked around by switching to a flowchart
Comparison with Other Diagrams
| Diagram Type | Core Purpose | Difference from Block |
|---|---|---|
| Block | Manual grid positioning | You control exact placement; the tradeoff is far weaker edge-routing and stability than a flowchart |
| Architecture | Small cloud/system topologies with icons | Has icons, mandatory anchors, but still no manual positioning |
| Flowchart | Process & decisions, general-purpose structure | Automatic but mature layout; the safe default for anything non-trivial |
Declaring a Chart
block-beta
columns 1
A["My Block"]
columns N sets a fixed column count; blocks placed after it wrap into new rows automatically. Note: title is not a valid statement here — like architecture-beta, it's silently accepted but has zero visual effect. Don't bother.
Basic Blocks and Connections
block-beta
columns 3
A["Block A"] B["Block B"] C["Block C"]
A --> B
B --> C
Only connect adjacent blocks. This example connects A→B and B→C — each edge spans one block. If you instead added A --> C (skipping over B), the edge would be drawn as a straight line from A's center to C's center — cutting directly through B's label. There's no anchor concept in block-beta like there is in architecture-beta; an edge is just a line between two block centers, with no awareness of what's in between.
Never place two blocks side-by-side without a space between them if you plan to connect them with an edge to something else — Mermaid's own docs call this out explicitly as a common mistake that breaks the layout.
Nested (Composite) Blocks
block-beta
columns 3
Frontend space Backend
space:3
block:db_cluster:3
columns 3
DB1[("Primary DB")] DB2[("Replica")] Cache[("Cache")]
end
Frontend --> Backend
Backend --> DB1
Backend --> Cache
block:groupId:N ... end creates a named container spanning N columns, which can declare its own columns for its internal grid. The default styling gives composite blocks a light background so they read as a distinct group.
Full Example: Network Topology
block-beta
columns 2
block:hq:2
columns 2
Router1["Core Router"]:2
Switch1["Switch A"] Switch2["Switch B"]
PC1["Workstations"] Server1[("File Server")]
end
space:2
block:branch:2
columns 2
Router2["Branch Router"]:2
AP1["Wi-Fi AP"] PC3["Workstations"]
end
hq --> branch
Key technique: connect group IDs, not internal nodes, for inter-group edges. hq --> branch draws a clean line from one composite block's boundary to the other's, without crossing anything inside either group. If you instead connected a specific node inside hq to a specific node inside branch (e.g. Router1 --> Router2), the edge is drawn straight through the layout and is far more likely to cross an internal block's label — confirmed by testing.
Limitations (confirmed by testing and GitHub issues)
Treat block-beta as the least stable diagram type in Mermaid's toolkit:
- No anchor points. Unlike architecture-beta, edges connect block centers, not sides — any edge that isn't between strictly adjacent blocks risks crossing something.
- Nested groups + column spans is fragile. Column-span context doesn't always propagate correctly through nesting; some shapes (round-edge) span their columns correctly, others don't.
- A real production crash exists:
Converting circular structure to JSON, triggered inside React/Next.js environments — Vercel's own examples repo hit this and replaced ablock-betadiagram with a flowchart as the fix, rather than working around it. - No
titlestatement (silently ignored, like architecture-beta).
Recommendation: use block-beta only for small, mostly-flat grids where exact positioning genuinely matters more than reliability. For anything else — more connections, deeper nesting, or anything you need to be robust across renderers — use a flowchart with subgraph instead (see Mermaid Flowcharts).
Quick Reference
| Syntax | Function |
|---|---|
block-beta |
Declare a block diagram |
columns N |
Set a fixed column count for the current grid |
id["Label"] |
Define a block |
id[("Label")] |
Define a cylinder-shaped block (e.g. for databases) |
id:N |
Make a block span N columns |
space / space:N |
Leave a gap of 1 or N columns |
block:groupId:N ... end |
Nested composite block spanning N columns |
A --> B |
Connect two adjacent blocks (avoid skipping over blocks) |
Next Step
For anything more complex than a small, mostly-flat grid, see Mermaid Flowcharts — it trades block-beta's manual positioning for far more mature, reliable layout.
To try the above code in MermZen, click Open Editor and paste the code there.