Can you build reusable styles in GraphViz?

(1) It's possible with annoying workarounds similar to the answer:

// define some nodes which shall have common style properties:
myNode1, myNode2, myNode3 [shape="box", style="filled, rounded", ...]

// now you can define custom style properties for each node, f.e. the labels
myNode1 [label="my fancy label for node 1"]
myNode2 [label="my fancy label for node 2"]

// you can then define another common style for other nodes:
myHexNode1, myHexNode2 [shape="hexagon", ...]

// now you can define custom style properties for each node, f.e. the lables
myHexNode1 [label="my hexnode 1 text"]
myHexNode2 [label="my hexnode 2 text"]

// and now the edges
myNode1 -> myHexNode1 -> myNode2 -> myHexNode2;

(2) By grouping elements in subgraph and defining the style properties locally within the subgraph as described in this answer.

(3) There has been a very nice feature request here which already describes the syntax. Anyway, at the moment nobody is working on it and it does not look like to be started soon.

Finally, this looks like this:

enter image description here


"Sometimes the answer is 'no'."

So, no. GraphViz lacks the notion of "named styles" seen in word processors like Microsoft Word and LibreOffice, and lacks the style "class" notion from HTML and CSS. Its formatting attributes are more primitive and, in many cases, must be explicitly stated.

You can set some defaults, as in its finite state machine example:

node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
node [shape = circle];

Here you get defaulting to the shape of a circle (the last shape defined), with explicit calling out of a handful of nodes that are previously declared under a previous default (doublecircle). This is a convenience for some designs, but it requires a good degree of preplanning (e.g. of the order items are declared). You can sometimes use the subgraph feature to help organize defaults by group, as this Stack Overflow answer shows.

But defaults are a small comfort to those of us used to expressive, simple type mechanisms. A look at the rest of the documentation confirms that, while you can use some HTML-styling elements for text, e.g., they are restricted to HTML tags such as <b> and <i>. This is primitive HTML styling circa 2001, prior to the spread of quality CSS.

Don't be fooled by the stylesheet attribute, either; it's only for SVG output, and is disappointingly much less general and valuable than it first seems.

So, long story short, "no." GraphViz has no built-in reusable style elements. If you want that, you will have to build that separately using a program, a macro-preproessor, or the like. Sorry!


Yes it does.

Use the class attribute in nodes or edges. Use the stylesheet attribute in the graph (or pass -Gstylesheet=whatever.css in the CLI.

The stylesheet is normal CSS. Classes wok just like in HTML.

You do need very latest graphviz for this to work.

Example:

https://ralsina.gitlab.io/boxes-book/part3/git_3.svg

If you look at the source you will see it loads https://ralsina.gitlab.io/boxes-book/styles/forest.css which has all the styles.

It works for SVG output (which is the good output ;-)


Yes you can, but not using GraphViz alone.

As stated before, the C preprocessor can be used to create some pretty good templates.

Example DOT file:

#define _STR(x) #x
#define STR(x) _STR(x)

#define STYLE1 shape="box",style="filled, rounded", fillcolor=lightyellow
#define _STYLE2_l(A,B) {{<ia>|<ib>}|A|B}
#define STYLE2(A,B) shape="record" label=STR(_STYLE2_l(A,B))

digraph Orthogonal {
    graph [rankdir=LR];

    a[STYLE1,label="a"];
    b[STYLE2(B1,B2)];
    c[STYLE1,label="c"];
    d[STYLE2(D1,D2)];

    a->b:ia;
    c->d:ib;
    b->c;
    b->d:ia;
}

Two style templates have been created. "STYLE1" is simply replaced by it's definition during preprocessing. "STYLE2" is a little more complex and shows the use of paramters/arguments within a template. It is constructed out of several macros.

The file can be rendered using:

cpp graph_file.gv | dot -Tpng >out.png

All output modes should work. This is the result:

Example Graph