Mermaid vs PlantUML Class Diagrams: Syntax and Examples

OnUML Team··7 min read
mermaidplantumlclass-diagramdiagram-as-codeuml

This article focuses only on class diagram expression. It does not cover broader tool differences such as Markdown support, documentation platform integration, ecosystem plugins, or rendering services. For those topics, see the series overview: Mermaid vs PlantUML: Which diagram-as-code tool should you choose in 2026?.

With that scope in mind, the conclusion is direct: Mermaid is enough for everyday class diagrams that explain domain models, service objects, interfaces, and simple inheritance. PlantUML is stronger when the diagram needs to behave more like formal UML documentation, especially for packages, namespaces, hidden details, association classes, complex notes, and consistent styling.

Both tools can express class names, attributes, methods, visibility, inheritance, composition, aggregation, dependency, implementation, cardinality, and notes. The real choice is usually not "can this tool draw inheritance?" It is whether the diagram needs richer UML elements, better model trimming, more complex package structure, or output that belongs in an architecture review.

A more accurate way to think about it is:

Mermaid wins on lightweight clarity. For product documentation, README files, technical proposals, and small to medium domain models, classDiagram is short, readable, and easy to embed in Markdown. If the class count is modest, grouping is simple, and styling requirements are light, Mermaid usually will not limit the diagram.

PlantUML wins on fuller UML semantics. It supports more declaration elements, including interface, enum, abstract class, record, dataclass, protocol, and exception. It also has mature package and namespace support, hide/remove/restore commands, association classes, linked notes, layout helpers, and skinparam styling. That makes it a better fit for complex design diagrams and long-lived architecture documentation.

This article is based on the official documentation and compares code and visual output through concrete examples:

Core differences in Mermaid vs PlantUML class diagrams

Comparison pointMermaidPlantUMLRecommendation
Classes, attributes, methodsSupportedSupportedBoth work
VisibilitySupports +, -, #, ~Supports +, -, #, ~Both work
Static and abstract membersSupports $ and * markersSupports explicit {static} and {abstract} markersPlantUML is clearer for formal UML diagrams
Inheritance, implementation, composition, aggregation, dependencySupportedSupportedBoth work
CardinalitySupported on both sides of relationshipsSupported on both sides of relationshipsBoth work
GenericsSupports ~T~, with limits for complex genericsSupports generic type expressionsPlantUML is better for complex type models
Interfaces, enums, abstract classesUsually expressed with annotationsHas interface, enum, abstract class, and related declarationsPlantUML is more explicit
Packages and namespacesSupports namespaceSupports package, namespace, and package stylingPlantUML is better for large models
Hidden members and trimmed viewsMostly configuration and limited syntaxSupports hide, remove, restore, and tag-based trimmingPlantUML is better for design reviews
NotesSupports note and note forSupports directional, floating, linked, field, and method notesPlantUML has finer note control
Association classesNot prominentSupportedChoose PlantUML for strict UML semantics
StylingSupports classDef, CSS classes, and themesSupports skinparam, colors, stereotype styling, and morePlantUML is better for consistent output rules

One-sentence summary:

Mermaid class diagrams are good at explaining structure; PlantUML class diagrams are better when you need to control structure, semantics, trimmed views, and output style together.

Mermaid can handle common class models

Some people assume that class diagrams require PlantUML as soon as inheritance, interfaces, composition, or cardinality appear. That is not accurate. Mermaid's class diagram syntax supports class members, visibility, return types, generics, common UML relationships, cardinality, annotations, notes, and direction. That covers most documentation-style class diagrams.

Here is an order domain model: Order contains multiple OrderItem objects, uses a PaymentMethod interface for payment, and is associated with Customer.

Mermaid code and diagram

classDiagram
  direction LR

  class Customer {
    +String id
    +String email
    +placeOrder()
  }

  class Order {
    +String id
    +OrderStatus status
    +Money total
    +addItem(productId, quantity)
    +checkout() PaymentResult
  }

  class OrderItem {
    +String productId
    +int quantity
    +Money price
    +subtotal() Money
  }

  class PaymentMethod {
    <<Interface>>
    +authorize(amount) PaymentResult
  }

  class CreditCardPayment {
    +String token
    +authorize(amount) PaymentResult
  }

  class OrderStatus {
    <<Enumeration>>
    CREATED
    PAID
    CANCELLED
  }

  Customer "1" --> "0..*" Order : places
  Order "1" *-- "1..*" OrderItem : contains
  Order --> PaymentMethod : uses
  PaymentMethod <|.. CreditCardPayment
  Order --> OrderStatus

PlantUML code and diagram

@startuml
left to right direction

class Customer {
  +id: String
  +email: String
  +placeOrder()
}

class Order {
  +id: String
  +status: OrderStatus
  +total: Money
  +addItem(productId, quantity)
  +checkout(): PaymentResult
}

class OrderItem {
  +productId: String
  +quantity: int
  +price: Money
  +subtotal(): Money
}

interface PaymentMethod {
  +authorize(amount): PaymentResult
}

class CreditCardPayment {
  +token: String
  +authorize(amount): PaymentResult
}

enum OrderStatus {
  CREATED
  PAID
  CANCELLED
}

Customer "1" --> "0..*" Order : places
Order "1" *-- "1..*" OrderItem : contains
Order --> PaymentMethod : uses
PaymentMethod <|.. CreditCardPayment
Order --> OrderStatus
@enduml

For a small to medium domain model like this, Mermaid already explains the structure clearly. It is not limited to a few boxes and lines; class members, interface markers, enum markers, composition, and cardinality are all expressible.

PlantUML declarations are closer to formal UML

Both tools can express interfaces and enums, but they do it at different semantic levels. Mermaid usually uses annotations such as <<Interface>> and <<Enumeration>> to describe the nature of a class. PlantUML can declare interface, enum, abstract class, and other elements directly.

Mermaid code and diagram

classDiagram
  class Repository {
    <<Interface>>
    +findById(id) Entity
    +save(entity)
  }

  class SqlRepository {
    +findById(id) Entity
    +save(entity)
  }

  class BaseEntity {
    <<Abstract>>
    +String id
    +createdAt Date
  }

  BaseEntity <|-- User
  Repository <|.. SqlRepository

PlantUML code and diagram

@startuml
interface Repository {
  +findById(id): Entity
  +save(entity)
}

class SqlRepository {
  +findById(id): Entity
  +save(entity)
}

abstract class BaseEntity {
  +id: String
  +createdAt: Date
}

class User

BaseEntity <|-- User
Repository <|.. SqlRepository
@enduml

Mermaid annotations work well for documentation. PlantUML declarations are better for formal modeling because readers can see the element type in both the syntax and the rendered diagram.

PlantUML is better for trimming and grouping large class diagrams

As class diagrams grow, the hard part is not "can the tool draw the model?" The hard part is "can the diagram show only what this reader needs?" The same domain model might show only public methods in product documentation, but show fields, abstract classes, package structure, and internal dependencies in a code design review.

PlantUML handles this kind of view management more naturally. It can group classes with package or namespace blocks, trim details with hide, show, and remove, and control output style with skinparam.

PlantUML code and diagram

@startuml
skinparam classAttributeIconSize 0
hide empty members

package "order.domain" {
  abstract class AggregateRoot {
    +id: String
    #raise(event)
  }

  class Order {
    -items: List<OrderItem>
    +checkout()
    +cancel()
  }

  class OrderItem {
    -productId: String
    -quantity: int
  }
}

package "payment.domain" {
  interface PaymentGateway {
    +authorize(orderId, amount): PaymentResult
  }

  class StripeGateway {
    +authorize(orderId, amount): PaymentResult
  }
}

AggregateRoot <|-- Order
Order *-- OrderItem
Order ..> PaymentGateway
PaymentGateway <|.. StripeGateway

note right of Order
  Public methods are kept visible
  for the architecture review.
end note
@enduml

Mermaid approximation

classDiagram
  namespace order.domain {
    class AggregateRoot {
      <<Abstract>>
      +String id
      #raise(event)
    }

    class Order {
      -List~OrderItem~ items
      +checkout()
      +cancel()
    }

    class OrderItem {
      -String productId
      -int quantity
    }
  }

  namespace payment.domain {
    class PaymentGateway {
      <<Interface>>
      +authorize(orderId, amount) PaymentResult
    }

    class StripeGateway {
      +authorize(orderId, amount) PaymentResult
    }
  }

  AggregateRoot <|-- Order
  Order *-- OrderItem
  Order ..> PaymentGateway
  PaymentGateway <|.. StripeGateway

  note for Order "Public methods are kept visible\nfor the architecture review."

Why PlantUML fits this case better

Mermaid can approximate this diagram, but the boundaries are different:

  • Mermaid namespace can provide basic grouping, while PlantUML package and namespace features are stronger for large models.
  • Mermaid can improve empty member boxes with settings such as hideEmptyMembersBox, while PlantUML can hide attributes, methods, classes, unconnected classes, or tagged elements more precisely.
  • Mermaid note for is enough for simple notes, while PlantUML directional notes, floating notes, linked notes, and field or method notes are better for complex review diagrams.
  • Mermaid classDef works for local styling, while PlantUML skinparam and stereotype styling are better for a consistent output standard.

This is PlantUML's real advantage in class diagrams. It is not about whether the tool can draw classes and relationships. It is about whether it can manage a model view that keeps growing.

Mermaid is better for embedded explanation diagrams

If the class diagram lives in a README, product technical note, lightweight ADR, or online documentation page, Mermaid has a clear advantage: the code is short, easy to read, and close to the surrounding Markdown.

Mermaid code and diagram

classDiagram
  class DiagramProject {
    +String id
    +String title
    +DiagramType type
    +save()
  }

  class Renderer {
    <<Interface>>
    +render(source) SvgResult
  }

  class MermaidRenderer {
    +render(source) SvgResult
  }

  class PlantUmlRenderer {
    +render(source) SvgResult
  }

  DiagramProject --> Renderer : uses
  Renderer <|.. MermaidRenderer
  Renderer <|.. PlantUmlRenderer

  note for Renderer "A renderer converts diagram source into SVG."

The purpose of this kind of diagram is not complete modeling. It is to help readers understand a module quickly. For that "explain this part of the code" use case, Mermaid's lightness is an advantage.

When to choose which

Choose Mermaid for class diagrams when:

  • You need to show a small or medium domain model.
  • You need to explain inheritance, implementation, composition, and dependency relationships between a few classes.
  • The diagram belongs in README files, Markdown documentation, product technical notes, or lightweight design docs.
  • Readers need to understand the structure quickly, not review full UML semantics.
  • The diagram size is controlled and you do not need multiple trimmed views.

Choose PlantUML for class diagrams when:

  • You need more formal UML class diagram semantics.
  • You need direct declarations such as interface, enum, abstract class, record, or dataclass.
  • You need package, namespace, package styling, or large model grouping.
  • You need to hide attributes, hide methods, remove elements, or show different review views.
  • You need association classes, field or method notes, linked notes, or more complex explanation structures.
  • You need stable visual rules for fonts, colors, stereotypes, and output style.

FAQ

Does Mermaid support inheritance, composition, and aggregation in class diagrams?

Yes. Mermaid class diagrams support inheritance, composition, aggregation, association, dependency, implementation, solid links, dashed links, and cardinality labels on both sides of a relationship. Do not rule out Mermaid only because the diagram has inheritance or composition.

Does Mermaid support interfaces and enums?

Yes, but the expression is annotation-based. You can use markers such as <<Interface>> and <<Enumeration>> to describe what a class represents. PlantUML can use declarations such as interface and enum directly, so the semantics are more explicit.

Is PlantUML always better for class diagrams?

No. If the diagram only explains relationships between a few classes, PlantUML's fuller feature set may not matter. Mermaid is lighter, easier to embed in Markdown, and often easier to maintain quickly. PlantUML is better for large models, formal UML, architecture reviews, and long-term style consistency.

How should I choose based only on diagram capability?

If the goal is "help readers understand the structure quickly," Mermaid is usually enough. If the goal is "express UML semantics accurately and maintain several complex views," PlantUML is the better fit.

Bottom line:

For class diagrams, Mermaid already has strong basic expressive power. PlantUML's advantage is richer UML elements, stronger view trimming, mature grouping, and better style control. Use Mermaid for lightweight explanation. Use PlantUML for formal modeling and complex architecture diagrams.

You can try the examples in the OnUML editor by switching between Mermaid and PlantUML modes.