Skip to main content

Styling edges

There are a few approaches you can take when it comes to styling your edges - JsPlumb provides an out of the box mapping from edge data to basic properties such as edge width, color etc, via the concept of Simple edge styles. You can also use CSS, or you can map a PaintStyle to your edges via a view. That's a lot of choice, so here we present a quick pros and cons for each option:

MethodProsCons
CSSClean separation of presentation from code. Allows usage of various SVG CSS effects. Allows styling all edges of some type uniformly.Does not support export to SVG. Does not support styling each edge individually. Does not support path outlines.
Paint stylesAllows styling all edges of some type uniformly. Supports export to SVG. Supports path outlines.Does not support styling each edge individually.
Simple edge stylesMinimal setup. Allows each edge to be styled individually. Seamlessly integrated with update and undo/redo. Supports path outlines. Supports export to SVG.Each edge needs its own styles declared in the backing data. Limited set of configurable properties.

Styling with CSS

Targeting the SVG path

Since JsPlumb uses SVG to render edges, you can target the artifacts that JsPlumb adds to the DOM via CSS. JsPlumb uses a class of jtk-connector on the SVG element it uses for each edge, and the edge itself is written as one or more path elements inside of that:

<svg class="jtk-connector">
<path d="..." class="jtk-connector-outline"></path>
<path d="..."></path>
</svg>

So to target the element used to render the path, you need a rule like this:

.jtk-connector path {
stroke-width:2;
stroke:cadetblue;
stroke-dasharray: 2;
}

Hover styles

To change the appearance of an edge on hover, use the :hover css meta class:

.jtk-connector path:hover {
stroke:orangered;
}

Note that the above example targets the path element on hover, but you can also target the parent SVG element of course:

.jtk-connector:hover {
outline:1px solid orangered;
}

Marching ants effect

It's simple to get this 'marching ants' effect via CSS with JsPlumb:

1. Define the CSS animation

Define a CSS animation with a single keyframe that sets the dash offset:

@keyframes dashdraw {
0% {
stroke-dashoffset:10;
}
}
2. Map the animation to a CSS rule
.animated-edge {
stroke-dasharray:5;
animation: dashdraw .5s linear infinite;
}
3. Use the cssClass property in an edge definition to map to this class (optional)
Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"view": {
"edges": {
"animated": {
"cssClass": "animated-edge"
}
}
}
});

We said that (3) is optional because if you just want to apply it to every edge in your dataset you can change the CSS rule shown in (2) to target every edge:

.jtk-connector {
stroke-dasharray:5;
animation: dashdraw .5s linear infinite;
}

Selected edges

When an edge is in a Toolkit's current selection, it has the CSS class jtk-surface-selected-connection applied to it. You can target this class to change the appearance of either the connector's parent element:

.jtk-surface-selected-connection {
outline:2px solid orangered;
}

or the path element representing the edge:

.jtk-surface-selected-connection path {
stroke:orangered;
}

Styling with PaintStyles

A PaintStyle is an object containing various properties to apply to a given type of edge. The definition of PaintStyle is:

Interface PaintStyle

NameTypeDescription
dashstyle?stringDash style for the path, in the format discussed here https://developer.mozilla.org/en-US/docs/Web/CSS/stroke-dasharray.
fill?stringFor overlays and endpoints, the color to use to fill the SVG shape
outlineStroke?stringThe color to use for path outline.
outlineWidth?numberThe width of the outline. The value here should indicate how much of an outline you want on each side of the path, _not_ the total width of the outline.
stroke?stringThe color to use to stroke the SVG path.
strokeWidth?numberThe width of the path.

With the exception of stroke all properties are optional. To setup an outline path, you must provide both outlineStroke and outlineWidth.

Mapping a PaintStyle in a view

You can map a PaintStyle to some specific edge type inside a view:

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"view": {
"edges": {
"redWithOutline": {
"paintStyle": {
"stroke": "red",
"strokeWidth": 3
}
}
}
}
});

Mapping a PaintStyle in the UI defaults

You can also set a default paint style via the defaults for some surface:

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"defaults": {
"paintStyle": {
"stroke": "red",
"strokeWidth": 3
}
}
});

Controlling the hit zone

By default, JsPlumb paints a single path element for each edge. If you want your users to be able to interact with your edges but your edges have a stroke width of only a couple of pixels, this can be difficult. To manage this we recommend using the outlineWidth and outlineStroke paint style properties to setup a hit zone:

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"defaults": {
"paintStyle": {
"stroke": "red",
"strokeWidth": 3,
"outlineStroke": "transparent",
"outlineWidth": 2
}
}
});
Calculating the outline width

When you provide outlineWidth and outlineStroke properties in a PaintStyle, the visible width of the outline is computed as:

w = strokeWidth + (2 * outlineWidth)

which is to say that the outlineWidth value you provide is applied to each side of the connector's path.

In this example we've used "transparent" for the outline color, which gives us the expanded hit zone without altering the appearance of each edge. You can, of course, use any color you like.

Hover styles

You can also provide a hoverPaintStyle property in your view, which JsPlumb will use to paint the edge when the mouse is hovering over it:

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"view": {
"edges": {
"redWithOutline": {
"paintStyle": {
"stroke": "red",
"strokeWidth": 3,
"outlineStroke": "orangered",
"outlineWidth": 2
},
"hoverPaintStyle": {
"stroke": "green",
"strokeWidth": 3,
"outlineStroke": "yellowgreen",
"outlineWidth": 4
}
}
}
}
});

Simple edge styles

Simple edge styles allow you to map values from an edge's backing data to its appearance.

Supported properties

  • color A valid CSS color, which will be used to paint the connector
  • lineWidth An integer value denoting the width, in pixels, of the connector.
  • outlineColor A valid CSS color, which will be used to paint the connector's outline.
  • outlineWidth An integer value denoting the width of the connector's outline. Note that this is not added to the lineWidth value; this values describes the total width of the outline. For instance, a lineWidth of 3 and an outlineWidth of 5 would result in a 1 pixel outline on either side of the connector path.

None of these properties are mandatory. JsPlumb will fall back to its defaults for these via the paintStyle mechanism if your edge data does not contain any of these properties.

Example

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"simpleEdgeStyles": true
});
toolkit.load({
type:"json",
data:{
nodes:[
{ id:"1" }, { id:"2" }
],
edges:[
{
source:"1",
target:"2",
data:{
color:"cadetblue",
lineWidth:3,
outlineColor:"pink",
outlineWidth:5
}
}
]
}
})

In this example the edge in our dataset will have a color of "cadetblue" and a stroke width of 3 pixels. It will also have an outline of 5 pixels each side, and the color of the outline will be pink. I think we can all agree it will look pretty fetching indeed.

And..that's it, basically. There's not much else to it. If you call updateEdge(...) with some new values for these properties, the edge will be updated.

Let's render that example from above. We'll render an edge with this backing data:

{
color:"cadetblue",
lineWidth:3,
outlineColor:"pink",
outlineWidth:5,
id:"edge"
}

(we gave it an id because we want to access it when you press a button in a moment; id is not a mandatory property).

If you now , we'll update those values:

toolkit.updateEdge("edge", {
color:"black",
outlineColor:"yellow",
lineWidth:2,
outlineWidth:3
})
note

Simple edge styles are switched on by default. If you do not want this behaviour in your app, you can save yourself some CPU cycles by setting simpleEdgeStyles:false in your render options.