Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom css classes for classDiagram nodes #1181

Closed
Baudin999 opened this issue Jan 6, 2020 · 9 comments · Fixed by #1599
Closed

Custom css classes for classDiagram nodes #1181

Baudin999 opened this issue Jan 6, 2020 · 9 comments · Fixed by #1599
Assignees
Labels

Comments

@Baudin999
Copy link

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.

@Baudin999 Baudin999 added Contributor needed Type: Other Not an enhancement or a bug labels Jan 6, 2020
@github-actions github-actions bot added the Status: Triage Needs to be verified, categorized, etc label Jan 6, 2020
@klemmchr klemmchr added Graph: Class Topic: Styling and removed Status: Triage Needs to be verified, categorized, etc labels Jan 6, 2020
@jgreywolf
Copy link
Contributor

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

@jgreywolf jgreywolf self-assigned this Feb 21, 2020
@jgreywolf
Copy link
Contributor

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

@Baudin999
Copy link
Author

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

@jgreywolf
Copy link
Contributor

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.

@Baudin999
Copy link
Author

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.

@ismarslomic
Copy link

ismarslomic commented Apr 9, 2020

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.

@jgreywolf
Copy link
Contributor

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

@TheSonOfThomp
Copy link

TheSonOfThomp commented Apr 15, 2020

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

@Baudin999
Copy link
Author

@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.

@jgreywolf jgreywolf mentioned this issue Aug 4, 2020
3 tasks
@knsv knsv closed this as completed in #1599 Aug 5, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Aug 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants