Mermaid vs PlantUML Class Diagrams: Syntax and Examples
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 point | Mermaid | PlantUML | Recommendation |
|---|---|---|---|
| Classes, attributes, methods | Supported | Supported | Both work |
| Visibility | Supports +, -, #, ~ | Supports +, -, #, ~ | Both work |
| Static and abstract members | Supports $ and * markers | Supports explicit {static} and {abstract} markers | PlantUML is clearer for formal UML diagrams |
| Inheritance, implementation, composition, aggregation, dependency | Supported | Supported | Both work |
| Cardinality | Supported on both sides of relationships | Supported on both sides of relationships | Both work |
| Generics | Supports ~T~, with limits for complex generics | Supports generic type expressions | PlantUML is better for complex type models |
| Interfaces, enums, abstract classes | Usually expressed with annotations | Has interface, enum, abstract class, and related declarations | PlantUML is more explicit |
| Packages and namespaces | Supports namespace | Supports package, namespace, and package styling | PlantUML is better for large models |
| Hidden members and trimmed views | Mostly configuration and limited syntax | Supports hide, remove, restore, and tag-based trimming | PlantUML is better for design reviews |
| Notes | Supports note and note for | Supports directional, floating, linked, field, and method notes | PlantUML has finer note control |
| Association classes | Not prominent | Supported | Choose PlantUML for strict UML semantics |
| Styling | Supports classDef, CSS classes, and themes | Supports skinparam, colors, stereotype styling, and more | PlantUML 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
namespacecan 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 foris enough for simple notes, while PlantUML directional notes, floating notes, linked notes, and field or method notes are better for complex review diagrams. - Mermaid
classDefworks for local styling, while PlantUMLskinparamand 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, ordataclass. - 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.