# ELK Layout Algorithm in Mermaid: Configuring Node Placement and Cycle-Breaking Strategies

> Explore the ELK layout algorithm in Mermaid. Learn to configure node placement and cycle breaking strategies for optimal diagram rendering. Master your layouts today.

- Repository: [mermaid-js/mermaid](https://github.com/mermaid-js/mermaid)
- Tags: deep-dive
- Published: 2026-02-23

---

**The ELK layout algorithm in Mermaid utilizes the Eclipse Layout Kernel (elkjs) to render complex hierarchical diagrams, allowing fine-grained control over node positioning and cycle resolution through the `nodePlacementStrategy` and `cycleBreakingStrategy` configuration options.**

The `mermaid-js/mermaid` repository integrates the **ELK (Eclipse Layout Kernel)** engine via the `@mermaid-js/layout-elk` package, providing advanced layout capabilities for flowcharts, class diagrams, and ER diagrams. This integration translates Mermaid graph definitions into optimized visual structures by mapping configuration options directly to the underlying `elkjs` library. Mastering the `nodePlacementStrategy` and `cycleBreakingStrategy` settings enables you to optimize layout performance, minimize edge crossings, and preserve logical node ordering in cyclic graphs.

## ELK Architecture in Mermaid

The ELK renderer is implemented in the standalone package `@mermaid-js/layout-elk`, which wraps the JavaScript port of the Eclipse Layout Kernel. In [`packages/mermaid-layout-elk/src/render.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid-layout-elk/src/render.ts) (lines 171–732), the rendering pipeline constructs an ELK graph object and populates it with layout options derived from the Mermaid configuration.

The core configuration mapping occurs where the renderer builds the `layoutOptions` object:

```typescript
elkGraph = {
  id: 'root',
  layoutOptions: {
    'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
    'elk.algorithm': algorithm,
    'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy,
    'elk.layered.cycleBreaking.strategy': data4Layout.config.elk?.cycleBreakingStrategy,
  },
  children: [],
  edges: [],
};

```

This code demonstrates how Mermaid passes your configuration values directly to the ELK engine's layered graph layout algorithm.

## Node Placement Strategy Configuration

The `nodePlacementStrategy` option controls how the ELK algorithm positions nodes within the computed layout layers. Defined in [`packages/mermaid/src/config.type.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/config.type.ts) (lines 99–101), this setting accepts four distinct strategies:

- **`BRANDES_KOEPF`** — The default strategy defined in [`packages/mermaid/src/defaultConfig.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/defaultConfig.ts) (lines 23–28). This advanced heuristic minimizes total edge length while respecting node ordering constraints, making it ideal for large, complex diagrams.

- **`SIMPLE`** — Places nodes on a coarse grid with minimal computational overhead. This strategy prioritizes layout speed over edge optimization, suitable for small diagrams or rapid prototyping scenarios.

- **`NETWORK_SIMPLEX`** — Employs a network simplex algorithm that respects topological relationships, producing balanced node distributions with improved edge routing for medium-sized graphs.

- **`LINEAR_SEGMENTS`** — Forces nodes onto linear segments within their layers, creating clean hierarchical visual flows particularly effective for flowcharts with strict level separations.

## Cycle-Breaking Strategy Configuration

When diagrams contain directed cycles, ELK must temporarily reverse specific edges to create a valid hierarchical layout. The `cycleBreakingStrategy` determines which edges are selected for reversal. The available options, defined in [`packages/mermaid/src/config.type.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/config.type.ts) (lines 103–111), include:

- **`GREEDY`** — A fast heuristic that makes locally optimal decisions at each step. While computationally efficient, it may produce sub-optimal edge reversal sets in complex cyclic structures.

- **`GREEDY_MODEL_ORDER`** — Combines greedy selection with respect for the source model order, serving as the default in recent Mermaid releases when preserving definition sequence is important.

- **`DEPTH_FIRST`** — Uses depth-first search traversal to identify cycles, performing well when graphs contain shallow feedback loops.

- **`MODEL_ORDER`** — Strictly respects the order of node definitions as they appear in the source model, ensuring that the visual layout reflects the logical sequence of declarations.

- **`INTERACTIVE`** — Supports user interaction for cycle resolution, though this is rarely used in programmatic rendering contexts.

In [`packages/mermaid-layout-elk/src/render.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid-layout-elk/src/render.ts) (line 729), the renderer passes this configuration value directly to the `elk.layered.cycleBreaking.strategy` property.

## Implementation Methods

You can configure these strategies through three primary methods: global initialization, per-diagram directives, or YAML front matter.

### Global JavaScript Configuration

Set default ELK options for all diagrams on a page by initializing Mermaid with the `elk` configuration object:

```javascript
import mermaid from 'mermaid';
import elkLayouts from '@mermaid-js/layout-elk';

mermaid.registerLayoutLoaders(elkLayouts);

mermaid.initialize({
  startOnLoad: true,
  defaultRenderer: 'elk',
  elk: {
    nodePlacementStrategy: 'LINEAR_SEGMENTS',
    cycleBreakingStrategy: 'GREEDY_MODEL_ORDER'
  }
});

```

The `defaultRenderer: 'elk'` directive activates the ELK layout engine, while the `elk` object maps directly to the options consumed in the render pipeline.

### Diagram-Level Directives

Override global settings for individual diagrams using the `init` directive within your Mermaid code block:

```mermaid
%%{init: {
  "defaultRenderer": "elk",
  "elk": {
    "nodePlacementStrategy": "SIMPLE",
    "cycleBreakingStrategy": "MODEL_ORDER"
  }
}}%%
flowchart TD
    A --> B
    B --> C
    C --> A

```

This approach allows specific diagrams to use alternative strategies without affecting the global configuration.

### YAML Front Matter

For static site generators and documentation platforms, specify ELK options in YAML front matter:

```yaml
---
mermaid:
  defaultRenderer: elk
  elk:
    nodePlacementStrategy: BRANDES_KOEPF
    cycleBreakingStrategy: GREEDY
---

```

Mermaid merges these values into the runtime configuration, applying them to all diagrams rendered on the page.

## Optimization Guidelines

Selecting appropriate strategies depends on your diagram's structural characteristics and performance requirements.

**Node placement** directly impacts visual compactness and readability. Complex diagrams with numerous interconnections benefit from `BRANDES_KOEPF`, while simpler graphs may render faster with `SIMPLE` or `LINEAR_SEGMENTS` without significant quality loss.

**Cycle-breaking** becomes critical when visualizing feedback loops or recursive relationships. If maintaining the source code's declaration order is essential—for instance, when the sequence reflects logical execution flow—choose `MODEL_ORDER` or `GREEDY_MODEL_ORDER`. For maximum layout speed in performance-critical applications, `GREEDY` provides the fastest computation at the potential cost of sub-optimal edge routing.

## Summary

- The ELK layout algorithm in Mermaid is implemented in [`packages/mermaid-layout-elk/src/render.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid-layout-elk/src/render.ts) and wraps the `elkjs` library to provide advanced graph layouts.
- **Node placement strategies** (`SIMPLE`, `NETWORK_SIMPLEX`, `LINEAR_SEGMENTS`, `BRANDES_KOEPF`) control how nodes are arranged within layers, with `BRANDES_KOEPF` serving as the default for complex diagrams.
- **Cycle-breaking strategies** (`GREEDY`, `DEPTH_FIRST`, `MODEL_ORDER`, `GREEDY_MODEL_ORDER`, `INTERACTIVE`) determine how directed cycles are resolved to create valid hierarchies.
- Configuration occurs through `mermaid.initialize()`, diagram-level `%%{init}%%` directives, or YAML front matter, with options defined in [`packages/mermaid/src/config.type.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/config.type.ts).
- The default configuration in [`packages/mermaid/src/defaultConfig.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/defaultConfig.ts) sets `nodePlacementStrategy` to `BRANDES_KOEPF`, while cycle-breaking defaults to `GREEDY` or `GREEDY_MODEL_ORDER` depending on the Mermaid version.

## Frequently Asked Questions

### What is the default node placement strategy in Mermaid's ELK layout?

The default strategy is **`BRANDES_KOEPF`**, as specified in [`packages/mermaid/src/defaultConfig.ts`](https://github.com/mermaid-js/mermaid/blob/main/packages/mermaid/src/defaultConfig.ts) (lines 23–28). This algorithm uses an advanced heuristic to minimize total edge length while maintaining node ordering constraints, making it suitable for large and complex diagrams where visual clarity is paramount.

### How does the cycle-breaking strategy affect diagram layout?

The cycle-breaking strategy determines which edges are temporarily reversed when ELK encounters directed cycles in your graph. This reversal creates a temporary acyclic structure required for hierarchical layout. The **`MODEL_ORDER`** strategy preserves your source code's declaration sequence, while **`GREEDY`** prioritizes computational speed. Your choice affects both the visual flow and the preservation of semantic relationships in cyclic graphs.

### Can I use ELK layout for all Mermaid diagram types?

No, the ELK layout engine supports specific graph-based diagram types including **flowcharts**, **class diagrams**, and **entity-relationship (ER) diagrams**. You must explicitly enable the ELK renderer by setting `defaultRenderer: 'elk'` in your configuration or using the `@mermaid-js/layout-elk` package with `mermaid.registerLayoutLoaders()`.

### When should I use the SIMPLE node placement strategy versus BRANDES_KOEPF?

Use **`SIMPLE`** for small diagrams or development scenarios where layout computation speed matters more than edge optimization. It places nodes on a coarse grid with minimal overhead. Use **`BRANDES_KOEPF`** for production diagrams with complex interconnections, as it implements sophisticated heuristics to minimize edge crossings and total edge length, resulting in more readable layouts for large graphs.