By Arthur Teboul//11 min read/Tutorial

Mermaid Class Diagram: Complete Syntax Guide with Examples

Mermaid class diagrams let you document object-oriented design, data models, and system architecture in plain text that lives alongside your code. Write the structure once inside a Markdown file, and any Mermaid-compatible renderer — GitHub, VS Code, MacMD Viewer, or mermaid.live — produces a polished UML class diagram automatically. No diagramming app, no drag-and-drop, no file format incompatibilities.

TL;DR: Start with classDiagram. Define classes with class Name { +Type attr +method() Return }. Use visibility prefixes +, -, #, ~. Connect classes with <|-- (inheritance), *-- (composition), o-- (aggregation), --> (association). Annotate with <<Interface>> or <<Abstract>>. Preview locally with MacMD Viewer or at mermaid.live.

What Are Mermaid Class Diagrams Used For?

Mermaid class diagrams model the static structure of a codebase using UML notation. They answer three practical questions: what classes exist, what data and behavior each class owns, and how classes relate to each other. Developers reach for them in three contexts:

  1. OOP design — sketch the class hierarchy before writing code. Catch design problems like missing abstractions, circular dependencies, or bloated god classes before they are expensive to fix.
  2. API documentation — show the shape of request/response DTOs and domain objects so that consumers understand the contract without reading source files.
  3. System architecture — document service boundaries, shared models, and dependency direction in a format that non-engineers can read.

Unlike PlantUML, which requires a Java server or a browser plugin, Mermaid class diagrams render in any Markdown-aware environment that supports Mermaid — including GitHub READMEs natively since 2022. For local Markdown files on macOS, MacMD Viewer ($19.99) renders them offline with zero configuration.

How Do You Define a Class in Mermaid?

Every Mermaid class diagram starts with the keyword classDiagram. Classes are declared with the class keyword, followed by the name and an optional body in curly braces. Here is a minimal example:

classDiagram
    class Animal {
        +String name
        +int age
        +makeSound() String
        #breathe() void
        -heartRate int
    }

The body lists attributes and methods. Attributes follow the format visibility Type name. Methods follow the format visibility name(params) ReturnType. Visibility is specified with a single character prefix:

PrefixVisibilityUML Equivalent
+PublicOpen circle
-PrivateClosed circle
#ProtectedHash
~Package / InternalTilde

Two special suffixes modify member semantics:

  • $ — static member (e.g., +getInstance()$ Instance)
  • * — abstract method (e.g., +makeSound()* String)

If you do not need to list members, you can declare a class in one line and define it inline in a relationship. But explicit class bodies make the diagram self-documenting and eliminate guesswork about what each class contains.

What Relationship Types Does Mermaid Support?

Relationships are the most important part of any class diagram. Mermaid supports eight relationship types, each corresponding to a standard UML arrow. Choosing the correct one is critical — using composition where aggregation is appropriate, or association where dependency fits better, produces diagrams that mislead readers about how the system actually works.

ArrowSyntaxRelationshipMeaning
Inheritance<|--Is-aChild extends Parent
Composition*--Has-a (strong)Child cannot exist without Parent
Aggregationo--Has-a (weak)Child can exist independently
Association-->UsesOne class knows about another
Link (solid)--RelatedGeneral undirected connection
Dependency..>Depends-onUses temporarily (parameter, return)
Realization..|>ImplementsClass fulfills an interface contract
Bidirectional<-->Both directionsMutual awareness

Here is a diagram showing all eight relationship types:

classDiagram
    class Vehicle
    class Car
    class Engine
    class Wheel
    class Driver
    class Fuel
    class Printable
    class Report
 
    Car <|-- Vehicle : inherits
    Car *-- Engine : composition
    Car o-- Wheel : aggregation
    Car --> Driver : association
    Car -- Fuel : link
    Report ..> Car : dependency
    Report ..|> Printable : realization
    Driver <--> Car : bidirectional

A few rules prevent the most common mistakes:

  • Inheritance <|-- — the closed arrowhead always points toward the parent. Write Dog <|-- Animal means Dog inherits Animal, which is wrong. Write Animal <|-- Dog to express that Dog extends Animal.
  • Composition *-- — the filled diamond is on the owner's side. Order *-- OrderItem means Order owns OrderItems; destroying the Order destroys its items.
  • Realization ..|> — the open arrowhead points toward the interface, not the implementing class. Serializable ..|> Report means Serializable implements Report, which is backwards. Write Report ..|> Serializable.

How Do You Add Cardinality Labels?

Cardinality labels describe how many instances participate in a relationship. Place them in quotes adjacent to each end of the relationship arrow:

classDiagram
    class Customer {
        +String email
        +placeOrder() Order
    }
    class Order {
        +DateTime createdAt
        +calculateTotal() float
    }
    class OrderItem {
        +int quantity
        +float unitPrice
    }
 
    Customer "1" --> "0..*" Order : places
    Order "1" *-- "1..*" OrderItem : contains

Common cardinality notations:

NotationMeaning
"1"Exactly one
"0..1"Zero or one (optional)
"1..*"One or more
"0..*" or "*"Zero or more
"n"Exactly n

Cardinality labels appear directly on the rendered arrow, making the multiplicity obvious without any accompanying prose. Use them on any relationship where the count is meaningful — especially compositions and associations in domain models.

How Do You Use Annotations for Interfaces, Abstract Classes, and Enumerations?

Annotations apply UML stereotypes to a class. They render as a label in double angle brackets above the class name and visually distinguish special class types from concrete implementations:

classDiagram
    class PaymentMethod {
        <<Interface>>
        +pay(amount float) bool
        +refund(amount float) bool
        +getTransactionId() String
    }
    class AbstractNotifier {
        <<Abstract>>
        +String recipient
        +send(message String)* void
        +formatMessage(content String) String
    }
    class PaymentStatus {
        <<Enumeration>>
        PENDING
        COMPLETED
        FAILED
        REFUNDED
    }
    class PaymentService {
        <<Service>>
        +processPayment(method PaymentMethod, amount float) bool
    }

The four most common annotations and when to use them:

AnnotationUse Case
<<Interface>>Pure contract — no implementation, only method signatures
<<Abstract>>Partial implementation — some methods are abstract (*)
<<Enumeration>>Fixed set of named constants
<<Service>>Stateless business logic class (DDD or Spring convention)

You can also add notes to specific classes using the note keyword:

note for PaymentMethod "All payment methods must implement this interface"

Notes render as callout boxes attached to the class in the diagram output.

How Do You Use Namespaces to Organize Large Diagrams?

When a diagram covers multiple packages or modules, namespace blocks group related classes under a labeled boundary:

classDiagram
    namespace Domain {
        class Product {
            +String name
            +float price
            +int stock
        }
        class Category {
            +String label
        }
    }
    namespace Application {
        class ProductService {
            <<Service>>
            +findById(id String) Product
            +updateStock(id String, delta int) void
        }
    }
    Product --> Category : belongsTo
    ProductService ..> Product : dependency

Namespace boundaries appear as labeled rectangles in the rendered output. They are purely visual — they do not change how relationships are drawn, and arrows can cross namespace boundaries freely. Use them whenever a diagram spans more than one layer or bounded context.

Real Example: E-Commerce OOP Design

The best way to learn class diagram syntax is to read a complete, realistic example. The following diagram models the core domain of an e-commerce system: users, products, carts, orders, and payments.

classDiagram
    class User {
        +String id
        +String email
        +String passwordHash
        +DateTime createdAt
        +register(email String, password String) User$
        +authenticate(password String) bool
        +getCart() Cart
    }
    class Product {
        +String id
        +String name
        +float price
        +int stockLevel
        +String categoryId
        +isInStock() bool
        +applyDiscount(pct float) void
    }
    class Cart {
        +String id
        +DateTime updatedAt
        +addItem(product Product, qty int) void
        +removeItem(productId String) void
        +calculateTotal() float
        +checkout() Order
    }
    class CartItem {
        +int quantity
        +float unitPrice
        +getSubtotal() float
    }
    class Order {
        +String id
        +DateTime placedAt
        +OrderStatus status
        +float totalAmount
        +confirm() void
        +cancel() void
        +getItems() CartItem[]
    }
    class Payment {
        <<Interface>>
        +pay(amount float) bool
        +refund(amount float) bool
        +getTransactionId() String
    }
    class CreditCardPayment {
        +String cardLastFour
        +String cardToken
        +pay(amount float) bool
        +refund(amount float) bool
        +getTransactionId() String
    }
    class OrderStatus {
        <<Enumeration>>
        PENDING
        CONFIRMED
        SHIPPED
        DELIVERED
        CANCELLED
    }
 
    User "1" --> "1" Cart : owns
    Cart "1" *-- "0..*" CartItem : contains
    CartItem "0..*" --> "1" Product : references
    Cart --> Order : checkout creates
    Order "1" *-- "1..*" CartItem : includes
    Order --> Payment : paid via
    CreditCardPayment ..|> Payment : implements
    Order --> OrderStatus : has status

Walking through the key design decisions in this diagram:

  • Cart *-- CartItem — composition, because CartItems have no meaning outside their Cart.
  • CartItem --> Product — association with "0..*" to "1", because a Product can appear in many carts but a CartItem references exactly one Product.
  • Cart --> Order — association with a label clarifying the relationship's intent (checkout creates).
  • CreditCardPayment ..|> Payment — realization, because CreditCardPayment implements the Payment interface contract.
  • <<Enumeration>> on OrderStatus — communicates that this is a fixed set of states, not a free-form class.

This diagram communicates the entire domain model to a new team member in under a minute. Adding a second payment method (e.g., PayPalPayment) requires one new class and one ..|> realization line — the interface design makes extension obvious.

What Are Common Mistakes in Mermaid Class Diagrams?

Several mistakes appear regularly when developers first adopt Mermaid class diagrams. Knowing them upfront saves debugging time.

Reversed inheritance arrow. Animal <|-- Dog reads as "Animal inherits Dog," which is wrong. The arrowhead points toward the parent. The correct syntax is Dog <|-- Animal (Animal is the parent, Dog is the child that extends it). If you think of it as "Dog is-a Animal," the arrow flows from Dog toward Animal.

Missing visibility prefix. Writing String name inside a class body without a prefix (+, -, #, ~) is valid syntax but produces no visibility indicator in the output. Omitting visibility makes diagrams less informative and harder to distinguish from pseudocode.

Confusing composition and aggregation. Use *-- (composition) only when the child's lifecycle is tied to the parent — deleting the parent deletes the children. Use o-- (aggregation) when the child can survive independently. Library *-- Book is wrong if books can be moved to another library. Library o-- Book is correct.

Realization arrow pointing the wrong way. ..|> points toward the interface, not toward the implementor. Printable ..|> Report says the interface implements the class, which is backwards. Write Report ..|> Printable.

Putting return type before method name. Mermaid uses the format +methodName(params) ReturnType — the return type comes last. Writing +String getName() (Java style) breaks the syntax.

Mermaid Class Diagrams vs. PlantUML

Both tools produce UML class diagrams from text. The choice depends on where your diagrams live.

FeatureMermaidPlantUML
RenderingBrowser-native, GitHub-nativeRequires Java server or online service
SyntaxLightweight, close to pseudocodeMore verbose, closer to formal UML
Markdown integrationNative (code fence)Requires plugin or preprocessing
Class diagram depthCovers most UML class featuresFull UML 2.x support
Namespace supportYes (namespace keyword)Yes (package keyword)
Notes/stereotypesLimited but functionalMore options
Offline rendering on MacMacMD Viewer, VS CodePlantUML VS Code extension

For most engineering teams using GitHub, Notion, or Confluence for documentation, Mermaid is the pragmatic choice: zero tooling overhead, native rendering in the platforms you already use. See our Mermaid diagrams in Confluence guide for setup steps.

For teams that need the full UML 2.x specification with advanced features like lifeline constraints or object diagrams, PlantUML provides more depth — at the cost of additional infrastructure.

How Do You Preview Mermaid Class Diagrams?

Four options cover every workflow:

  1. MacMD Viewer ($19.99) — open any .md file containing a classDiagram and the diagram renders instantly. Native SwiftUI, works offline, 2 MB on disk. The bundled QuickLook extension lets you press Space in Finder to preview diagrams without opening the app. See the Mermaid viewer feature page for details. Available on the /download page.
  2. Mermaid Live Editor — paste your syntax and see the output side by side. Export as SVG or PNG. Best for iteration before committing to a file. See our Mermaid Live Editor guide for tips.
  3. VS Code — install the Markdown Mermaid extension, open any .md file, and press Cmd+Shift+V to render all diagrams in the preview pane.
  4. GitHub — push a .md file with a ```mermaid fence and GitHub renders the class diagram natively on the repository page.

For a comparison of browser-based Mermaid tools, see online Mermaid diagram tools.

Conclusion

Mermaid class diagram syntax covers the full OOP design surface: classes with typed attributes and methods, eight relationship types with cardinality labels, visibility modifiers, annotations for interfaces and abstract classes, namespace grouping, and notes. The text lives in version control alongside the code it documents, so diagrams stay accurate as the codebase evolves.

Start with the e-commerce example above. Replace the class names and members with your own domain model, run it through MacMD Viewer or mermaid.live, and you have production documentation in under ten minutes. For other Mermaid diagram types, see the flowchart syntax guide, sequence diagram guide, and ER diagram guide.

Ready to read Markdown beautifully?

Native macOS viewer with Mermaid diagrams, syntax highlighting, and QuickLook. One-time purchase, no subscription.

Buy for $19.99

Continue reading with AI

Summarize in ChatGPT🔍Research in PerplexityAsk Google AI

Content licensed under CC BY 4.0. Cite with attribution to MacMD Viewer.

Related Articles

Guide

Mermaid Diagrams: Complete Guide for Developers (2026)

Mermaid diagram viewer searches up 1,015% YoY (DataForSEO, 2026). Everything about Mermaid.js — syntax, diagram types, tools, viewers, and best practices.

Tutorial

Mermaid ER Diagram: Complete Syntax Guide (2026)

Full Mermaid ER diagram syntax reference — entities, attributes, relationship notation, PK/FK keys, and real-world examples for database documentation.

Tutorial

Best Free Mermaid Live Editor — Flowcharts, Sequence & Gantt (2026)

Use Mermaid Live Editor to create flowcharts, sequence diagrams, and Gantt charts for free — no signup. Paste syntax, preview instantly, export PNG/SVG.