Fine-Tuning Mermaid Graph Layout with ELK Options: mergeEdges, forceNodeModelOrder, and considerModelOrder

To fine-tune graph layouts in Mermaid, configure the elk options—mergeEdges, forceNodeModelOrder, and considerModelOrder—either globally via mermaid.initialize() or per-diagram using the %%{init: ...}%% directive to control edge bundling and node ordering in ELK-rendered diagrams.

The Mermaid diagramming library leverages the Eclipse Layout Kernel (ELK) engine for sophisticated graph layouts in flowcharts, ER diagrams, and class diagrams. According to the mermaid-js/mermaid source code, these ELK options are exposed through the MermaidConfig.elk interface, allowing precise control over how nodes are ordered and edges are rendered.

Where ELK Options Are Defined

The ELK configuration schema resides in packages/mermaid/src/config.type.ts, where the elk property of MermaidConfig defines the available options. Default values are established in packages/mermaid/src/defaultConfig.ts, setting mergeEdges to false, forceNodeModelOrder to false, and considerModelOrder to 'NODES_AND_EDGES'.

During rendering, these options are mapped to ELK-specific layout parameters in packages/mermaid-layout-elk/src/render.ts (approximately lines 720–730). The renderer constructs an elkGraph object with a layoutOptions property that translates Mermaid configuration keys into ELK-layered directives:

let elkGraph: any = {
  layoutOptions: {
    'elk.layered.mergeEdges': data4Layout.config.elk?.mergeEdges,
    'elk.layered.crossingMinimization.forceNodeModelOrder':
      data4Layout.config.elk?.forceNodeModelOrder,
    'elk.layered.considerModelOrder.strategy': data4Layout.config.elk?.considerModelOrder,
  },
};

Configuring ELK Layout Options

You can supply ELK configuration at two scopes: globally for all diagrams or locally for a single diagram using initialization directives.

Global Configuration

Use mermaid.initialize() to set default ELK behavior across your entire application:

mermaid.initialize({
  startOnLoad: false,
  flowchart: { defaultRenderer: "elk" },
  elk: {
    mergeEdges: true,
    forceNodeModelOrder: true,
    considerModelOrder: "PREFER_NODES",
    nodePlacementStrategy: "BRANDES_KOEPF"
  }
});

Per-Diagram Configuration

Override global settings for individual diagrams using the %%{init: ...}%% directive at the top of your Mermaid syntax:

%%{init: {
  "flowchart": { "defaultRenderer": "elk" },
  "elk": {
    "mergeEdges": true,
    "forceNodeModelOrder": true,
    "considerModelOrder": "PREFER_EDGES"
  }
}}%%
flowchart-elk TD
    A --> B
    A --> C
    B --> D
    C --> D

How Each Option Affects Layout

Understanding the interaction between these three parameters is essential for controlling visual density and node hierarchy.

mergeEdges: Bundling Parallel Connections

When mergeEdges is set to true, the ELK engine combines multiple edges sharing the same source and target nodes into a single bundled path. This reduces visual clutter in dense graphs but obscures individual edge routing. When set to false (the default), each edge maintains its distinct trajectory, which is preferable when tracking specific relationship paths is critical.

forceNodeModelOrder: Preserving Source Sequence

Setting forceNodeModelOrder to true instructs the layout algorithm to respect the exact order in which nodes appear in your Mermaid source code during the crossing-minimization phase. This is particularly valuable for pipeline diagrams or sequential processes where the textual order carries semantic meaning. By default (false), ELK may reorder nodes to minimize edge crossings, potentially disrupting the intended left-to-right or top-to-bottom flow.

considerModelOrder: Balancing Order and Crossings

The considerModelOrder parameter accepts four string values that determine how strictly ELK adheres to model order versus optimizing for crossing reduction:

  • 'NONE': ELK freely reorders nodes and edges to achieve minimal crossings, ignoring the source order entirely.
  • 'NODES_AND_EDGES' (default): ELK attempts to preserve both node and edge order while still allowing necessary adjustments to reduce crossings.
  • 'PREFER_NODES': Prioritizes keeping nodes in their defined sequence, accepting additional edge crossings if necessary to maintain node order.
  • 'PREFER_EDGES': Favors maintaining edge order and directionality, which may result in slight node reordering but preserves the flow of connections.

Practical Fine-Tuning Workflow

Follow this iterative process to optimize your ELK-rendered diagrams:

  1. Enable the ELK renderer by setting flowchart.defaultRenderer to "elk" and using the flowchart-elk diagram type.
  2. Activate mergeEdges if parallel edges between identical nodes create excessive visual noise.
  3. Enable forceNodeModelOrder when the sequence of nodes in your source code represents a fixed pipeline or chronological process.
  4. Select considerModelOrder strategy based on your priority: use PREFER_NODES for stable node positioning or PREFER_EDGES for consistent connection flow.
  5. Validate output by rendering the diagram and adjusting values to balance between crossing minimization and order preservation.

Summary

  • Configuration location: ELK options are defined in packages/mermaid/src/config.type.ts and default values are set in packages/mermaid/src/defaultConfig.ts.
  • Runtime mapping: Options are translated to ELK-layered parameters in packages/mermaid-layout-elk/src/render.ts using the elk.layered.* namespace.
  • mergeEdges: Controls whether parallel edges are bundled (true) or drawn separately (false).
  • forceNodeModelOrder: When true, prevents ELK from reordering nodes during crossing minimization.
  • considerModelOrder: Accepts NONE, NODES_AND_EDGES, PREFER_NODES, or PREFER_EDGES to balance order preservation against crossing reduction.
  • Usage scope: Configure globally via mermaid.initialize() or per-diagram via %%{init: {"elk": {...}}}%% directives.

Frequently Asked Questions

What is the difference between forceNodeModelOrder and considerModelOrder?

forceNodeModelOrder is a boolean that strictly prevents node reordering during crossing minimization when set to true, while considerModelOrder offers granular control through four strategy options (NONE, NODES_AND_EDGES, PREFER_NODES, PREFER_EDGES) that allow ELK to balance order preservation against crossing optimization. Use forceNodeModelOrder for absolute sequence enforcement and considerModelOrder for flexible, strategy-based ordering.

Why are my edges not merging despite setting mergeEdges: true?

Edge merging only occurs when multiple edges share the identical source and target nodes. If your diagram contains edges between different node pairs, they cannot be merged. Additionally, ensure you are using the elk renderer (flowchart-elk) rather than the default Dagre-based renderer, as mergeEdges is specific to the ELK layout engine implemented in packages/mermaid-layout-elk/src/render.ts.

Can I use ELK layout options with all Mermaid diagram types?

ELK layout options apply specifically to diagrams that support the ELK renderer, primarily flowcharts (flowchart-elk), ER diagrams, and class diagrams. The detector logic in packages/mermaid/src/diagrams/flowchart/elk/detector.ts determines ELK eligibility. Diagrams using the default Dagre renderer ignore the elk configuration object entirely.

How do I migrate from the default renderer to ELK to use these options?

Change your diagram declaration from flowchart TD to flowchart-elk TD and ensure your configuration includes flowchart: { defaultRenderer: "elk" }. Then populate the elk configuration object with your desired mergeEdges, forceNodeModelOrder, and considerModelOrder values. Note that ELK layouts may differ significantly from Dagre layouts, so visual adjustments might be necessary after migration.

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 →