Mermaid: Custom css classes for classDiagram nodes

Created on 6 Jan 2020  路  9Comments  路  Source: mermaid-js/mermaid

Hi, I'm trying to create bigger models and want to have different colored elements for different types of nodes in my class diagram.

For example, in the next image I would like the Student to be colored orange.

image

In order to do this I'd like to add a custom css class to my model and style the svg accordingly. Is this possible?

If not, the <<something>> notation seems a perfect way of adding a classifier to the resulting SVG.

Class Help wanted! Styling Other

Most helpful comment

For class diagrams the only way to modify the styling is via the steps outlined in documentation here: http://mermaid-js.github.io/mermaid/#/classDiagram?id=styling

Right now it is not possible to set custom styles for specific/discrete class diagram entities.

This is possible for other diagrams, and that functionality could be ported over from somewhere like how flowchart diagram handles this

All 9 comments

For class diagrams the only way to modify the styling is via the steps outlined in documentation here: http://mermaid-js.github.io/mermaid/#/classDiagram?id=styling

Right now it is not possible to set custom styles for specific/discrete class diagram entities.

This is possible for other diagrams, and that functionality could be ported over from somewhere like how flowchart diagram handles this

I am currently working on an implementation for this, using the styling functionality from flowcharts as a base

I don't know if I'm allowed to add a tip/comment...

I'd use attributes. Class diagrams are different than flowcharts. People tend to want to annotate where the class diagrams have changed and where the accents lie.

If possible an annotation to the diagram would work really well, for example:

classDiagram
    Animal <|-- Duck
    Animal <|-- Fish
    Animal <|-- Zebra
    Animal : +int age
    Animal : +String gender
    Animal: +isMammal()
    Animal: +mate()
       <<animal>> Animal

    class <<changed>> Duck {
        +String beakColor
        <<useless>> +swim() 
        +quack()
    }
    class Fish{
        -int sizeInFeet
        -canEat()
    }
    class Zebra{
        +bool is_wild
        +run()
    }

This is just a thought, but it would work well enough and will give you the flexibility you need to annotate anything as a class. I think these annotations, because they are already in the parser due to the "interfaces" could be easily parser. They also do not collide with other syntax.

Different ways of annotating might better. The best way ofc would be to use css notation:

classDiagram
    Animal <|-- Duck
    Animal <|-- Fish
    Animal <|-- Zebra
    Animal : +int age
    Animal : +String gender
    Animal: +isMammal()
    Animal: +mate()
       .animal Animal

    class .changed Duck {
        +String beakColor
        .useless .method .swim +swim() 
        +quack()
    }
    class Fish{
        -int sizeInFeet
        -canEat()
    }
    class Zebra{
        +bool is_wild
        +run()
    }

Not sure about collisions though...

Again, if I'm out of line, please let me know

I don't know if I'm allowed to add a tip/comment...

Of course you are!

class <> Duck {
+String beakColor
<> +swim()
+quack()

So, the idea being that you could then have something at the end like:

style changed background-color:#ffffff; ?

Actually, I think I like the .changed format a little better.

The .changed format is more intuitive but also more related to the CSS syntax. I personally like the . notation the best.

The actual styling can be done at the end of the diagram:

style changed background-color:#ffffff;

Or in a separate stylesheet of course.

I'm supporting this feature request, since I also would love to style single elements in Class Diagram separately! I would though argue that it is quite important that styling mechanisms across different Diagrams are consistent.

Specially since mermaidjs is useful for automating diagram generations. Having different styling mechanisms depending on Diagram style makes the scripts more complex, as well as that users writing diagrams manually needs to check the doc for each Diagram style.

So my five cents goes to reusing style mechanisms from the Flowchart.

The problem that I have run into with implementing styling is related to the way that members are defined for classes. The use of : between the class name and member means that the parser thinks you are trying to define this relationship when it gets to the class definition.

As you said, I want to keep the implementation the same as it is being used with other diagrams...

Ive been on "hiatus" from the project the past month or so to deal with other issues. You know, just some random things going on with family, the world, whatever ;)

Im getting ready to start up again, and this is one of the main issues I intend to come back to

Not sure if this is the spot to mention this, but I've noticed it's tough to write styles in external CSS because of the specificity of the elements.

When mermaid initializes, it creates an svg with a random id. The autogenerated CSS then targets this id in the CSS selector. Trying to write CSS that targets certain elements is not possible without either a) knowing the unique id or b) using !important. Neither of these follow CSS best practices.

Example:

/* Set the default color of each rectangle */
#mermaid-1586982669110 g.classGroup rect {
  fill: var(--color-blue-light);
  stroke: var(--color-blue);
}

/* or */
g.classGroup rect {
  fill: var(--color-blue-light) !important;
  stroke: var(--color-blue) !important;
}

Additionally, it's hard to select a specific classGroup with CSS as well, since the ids aren't easily predictable either. My workaround is to use the attribute includes selector and look for an id that includes the Class name.

/* Set the color of the Student class */
g.classGroup[id*=classid-Student-]  rect {
  fill: var(--color-purple-light) !important;
  stroke: var(--color-purple) !important;
}

Recommendation:
My recommendation for the first problem is to reduce the specificity of the default selectors. I don't see any need to target #mermaid-xxxxx, when simply targeting .mermaid would provide a sufficient level of scoping.

For the second, unless there's a reason I'm missing for appending a number to the classGroup id, I'd recommend removing that number. Further, since class names should be unique, it seems that simply using the Class name as the classGroup id would suffice.
E.x. The selector .mermaid g.classGroup#Student should target the Student class object

@TheSonOfThomp your suggestion would indeed solve a lot of difficulty finding the right node. It would not solve the usecase where you'd specifically wanted to add a class to a node. For example:

I use these diagrams to indicate where the changes are in my solution design. For added classes I use red, for changed classes I use orange. These correspond with the statuses new and changed. Just being able to style the node by name would not be sufficient.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gvlx picture gvlx  路  5Comments

The-Alchemist picture The-Alchemist  路  4Comments

lwalker-kforce picture lwalker-kforce  路  3Comments

deftdawg picture deftdawg  路  3Comments

PaoloneM picture PaoloneM  路  4Comments