bpmn-visualization: All you need to know about styling BPMN elements
Tags: tutorial, bpmn, visualization, typescript
Published: 2023-07-21 09:23:05


In this article, we're going to dive deep into the capabilities of the _[bpmn-visualization](https://github.com/process-analytics/bpmn-visualization-js)_ Typescript library, with a specific focus on managing styles. You'll learn how to use its APIs to set styles and, when necessary, revert them back to their default state. Additionally, we'll feature some advanced usage scenarios to provide you with inspiration for your own use.

If you're just getting started with _bpmn-visualization_, we recommend that you take a look at our [Getting Started](https://dev.to/process-analytics/getting-started-with-bpmn-visualization-3dno) tutorial. It provides a step-by-step guide on how to set up and begin using the library. 

You can try out and experiment with the APIs in one of our preconfigured live environments, available [here](https://cdn.statically.io/gh/process-analytics/bpmn-visualization-examples/master/examples/index.html) (see the **'Miscellaneous'** section).

So let's dive in 🏊!

<h1>Setting styles in bpmn-visualization</h1>

There are two primary ways to go about setting styles of BPMN elements: via CSS or programmatically. Let's delve into these two methods.

<h2>Styling with CSS: The addCssClasses API</h2>

The first method involves CSS, the cornerstone technology used to apply stylistic choices to elements on a web page. To use CSS for styling your BPMN elements, _bpmn-visualization_ provides the [`addCssClasses`](https://process-analytics.github.io/bpmn-visualization-js/api/classes/BpmnElementsRegistry.html#addCssClasses) API. This method is especially useful when you've already defined CSS class names that you wish to apply to your BPMN elements. 

In order to use `addCssClasses`, begin by defining your styles in your stylesheet, assigning a unique class name to each style. You can then apply these classes to your BPMN elements using the API. 

To illustrate, let's consider an example where we're styling activities to indicate an error state. Here's how you could define such a CSS class in your CSS file:

```CSS
/* Define your CSS class in your CSS file */ 
/* CSS class for an activity in error */ 
.bpmn-activity-error > rect { 
  fill: Tomato !important; 
  fill-opacity: 15% !important; 
  stroke: Tomato; 
}
```

Once you've defined your CSS class, apply it in your JavaScript or TypeScript code. This can be done by calling the `addCssClasses` API, which accepts the IDs of one or multiple BPMN elements, along with the CSS classes to be applied. Here's an example of how you can add the `bpmn-activity-error` class to two different activities:

```JS
// Create a new instance of BpmnVisualization
const bpmnVisualization = new BpmnVisualization(...);

// Load your BPMN diagram
bpmnVisualization.load(...);

// Apply the CSS class to a BPMN element
bpmnVisualization.bpmnElementsRegistry.addCssClasses(['task_id1', 'task_id2'], 'bpmn-activity-error');
```

For a more in-depth explanation of styling BPMN elements through CSS, be sure to check out our [Getting Started](https://dev.to/process-analytics/getting-started-with-bpmn-visualization-3dno) tutorial.

<h2>Dynamic styling: The updateStyle API</h2>

There might be cases where the style of a BPMN element is not known beforehand, or needs to change dynamically based on certain conditions. In these cases, the ability to programmatically apply styles is necessary.

This is where the [`updateStyle`](https://process-analytics.github.io/bpmn-visualization-js/api/classes/BpmnElementsRegistry.html#updateStyle) API comes into play. The `updateStyle` API allows you to alter the style of BPMN elements directly within your code. This offers the flexibility to adjust styles instantly and responsively. 

Much like the `addCssClasses` method, `updateStyle` accepts the identifiers of one or more BPMN elements, along with a set of style properties defined through the [`StyleUpdate`](https://process-analytics.github.io/bpmn-visualization-js/api/types/StyleUpdate.html) type. The properties that can be adjusted are dependent on the type of BPMN element: edge or shape (e.g., activities, events, gateways, etc.). 

Let's consider the following example:

```JS
bpmnVisualization.bpmnElementsRegistry.updateStyle(
  ['task_id1', 'task_id2'], { 
    fill: { color: "blue", opacity: 15 }, 
    font: { opacity: 40 }, 
    stroke: { color: "blue", width: 3 }, 
    opacity: 30
});
```
In this instance, the style is directly applied to the BPMN elements identified by `task_id1` and `task_id2`. 

<h1>Resetting styles in bpmn-visualization</h1>

Inevitably, there will be cases where you want to reset the styles applied to your BPMN elements, either returning them to their default state or preparing them for a new style. _bpmn-visualization_ provides easy-to-use APIs for this as well, mirroring the ways you can set styles.

<h2>Resetting CSS classes: The removeCssClasses API</h2>

You can easily remove classes for styles that have been applied using CSS with the `addCssClasses` API, by using the [`removeCssClasses`](https://process-analytics.github.io/bpmn-visualization-js/api/classes/BpmnElementsRegistry.html#removeCssClasses) API, providing the IDs of the BPMN elements, and providing the names of the CSS classes you want to remove. If you want to remove all CSS classes, you can do so with a call to [`removeAllCssClasses`](https://process-analytics.github.io/bpmn-visualization-js/api/classes/BpmnElementsRegistry.html#removeAllCssClasses)</code>.

 Here's an example:

```JS
// Remove one or more CSS classes
bpmnVisualization.bpmnElementsRegistry.removeCssClasses(['task_id1', 'task_id2'], ['bpmn-activity-error']);

// Remove all CSS classes
bpmnVisualization.bpmnElementsRegistry.removeAllCssClasses(['task_id1', 'task_id2']);
```

<h2>Resetting dynamic styles: The resetStyle and updateStyle APIs</h2>

_bpmn-visualization_ provides a couple of options for programmatically applied styles. If you want to completely reset the style of a BPMN element, you can use the [`resetStyle`](https://process-analytics.github.io/bpmn-visualization-js/api/classes/BpmnElementsRegistry.html#resetStyle) API. Just pass the IDs of the BPMN elements to this API and it will clear all style settings applied through the `updateStyle`API. Here's an example:

```JS
// Reset the style of a BPMN element 
bpmnVisualization.bpmnElementsRegistry.resetStyle(['task_id1', 'task_id2']);
```

If, however, you want to reset some specific style properties while leaving others intact, you can use the `updateStyle` API. Instead of setting the property to a specific value, you pass the value as `default`. Here's an example:

```JS
// Reset specific style properties of a BPMN element
bpmnVisualization.bpmnElementsRegistry.updateStyle('task_id1', { 
  fill: {color: 'default', opacity: 'default'},
  stroke: 'default' 
});
```

In this case, the fill and stroke properties are reset to their default values, while other style settings remain unchanged.

And that's it for the basics of bpmn-visualization's styling APIs. In the next section, we'll be looking at some more advanced usage scenarios, so keep reading 👌

<h1>Advanced usage scenarios</h1>


Beyond the basics, _bpmn-visualization_ can be used in a multitude of scenarios to address your specific needs. To illustrate this, we'll examine two practical applications of the library: **interactive styling** and **data-driven styling**.

<h2>Interactive styling</h2>

Interactive styling brings your BPMN diagrams to life by enabling them to respond to user actions. This could include actions like highlighting an element on hover, changing the style upon clicking, or indicating the active task in a process.

Our team has prepared different demos that showcase how to implement interactive styling using _bpmn-visualization_. Although the library does not currently support attaching event listeners directly to BPMN elements, we can still achieve interactivity by accessing the corresponding HTML elements.

Here's a code snippet that shows how to change the style of a BPMN element while the mouse is hovered on it, as it is done in the [Draw me a path](https://cdn.statically.io/gh/process-analytics/bpmn-visualization-examples/v0.37.0/demo/draw-path/index.html) demo:

```JS
// Retrieve the BPMN element using its ID
const bpmnElementId = 'task_id';
const bpmnElement= bpmnVisualization.bpmnElementsRegistry.getElementsByIds(bpmnElementId)[0];

// Retrieve the corresponding HTML element
const htmlElement = bpmnElement.htmlElement;

// Add a mouse event listeners to the HTML element
htmlElement.onmouseenter = () => {
    // Change the style of the corresponding BPMN element
    bpmnVisualization.bpmnElementsRegistry.updateStyle(bpmnElementId, {
     stroke: 'MediumVioletRed',
     font: {color: 'MediumVioletRed'}
    });
};

htmlElement.onmouseleave = () => {
    // Reset the style of the corresponding BPMN element
    bpmnVisualization.bpmnElementsRegistry.resetStyle(bpmnElementId);
};
```

In this snippet, we first retrieve the BPMN element using its ID by calling [`getElementsByIds`](https://process-analytics.github.io/bpmn-visualization-js/api/classes/BpmnElementsRegistry.html#getElementsByIds). We then access the corresponding HTML element. After this, we add hover event listeners to this HTML element. As a result, when the mouse hovers over this HTML element, the style of the corresponding BPMN element changes. As soon as the mouse leaves, the style resets to its original state. 

Below is a screenshot from the demo illustrating the final outcome:

![Example of interactive styling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hzd2qz6ujpn6hf7r7wk2.gif)

For more inspiration on interactive styling use cases, we invite you to explore the additional interactive features in our [Draw me a path](https://cdn.statically.io/gh/process-analytics/bpmn-visualization-examples/v0.37.0/demo/draw-path/index.html) and [Bonita Day 2023](https://process-analytics.github.io/bonita-day-demo-2023/) demos. You might also be interested in checking out an example of [integration with the Vue framework](https://github.com/process-analytics/bpmn-visualization-examples/blob/master/projects/typescript-vue/README.md), contributed by our amazing community. Happy exploring! 🤗

<h2>Data-driven styling</h2>

Data-driven styling allows you to customize the appearance of BPMN diagrams based on associated data. This can be particularly useful when you want to display certain characteristics or metrics related to your process, such as frequency or performance statistics, directly on your BPMN diagrams. 

For example, consider one of our demos that [integrates the bpmn-visualization library with pm4py](https://github.com/process-analytics/bpmn-visualization-pm4py). In this demo, we perform process discovery, compute frequency of execution statistics, carry out conformance checking, and then visualize the results using _bpmn-visualization_. 

One interesting aspect of this demo is how it handles the computation and visualization of process statistics. The first step involves using the [`scaleSequential`](https://d3js.org/d3-scale/sequential) function from the [D3](https://d3js.org/) library to map frequency statistics to a color gradient, ranging from light blue to dark blue as shown in the code snippet below:

```JS
// Create a D3 scale to map frequency to a color
const colorScale = d3.scaleSequential()
  .domain([0, 1]) // Initialize domain with dummy values
  .interpolator(d3.interpolatePuBu);
```

Next, we use the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to retrieve frequency statistics computed in the backend by _pm4py_. After obtaining these statistics, we call the `visualizeFrequency` function to visualize the results on our BPMN diagram:

```JS
// Compute frequency statistics using pm4py in the backend
fetch(`${apiUrl}/stats/frequency`)
    .then(response => response.json())
    .then(data => visualizeFrequency(data))
    .catch(error => console.log(error));
```

For clarity, let's examine key portions of the `visualizeFrequency` function. In the code snippet below, we show how this function updates the fill color and the color of labels for activities based on their frequency of execution:

```JS
// Function to visualize frequency data on BPMN elements
function visualizeFrequency(stats) {
    // Update the domain of colorScale with the actual values
    colorScale.domain([0, d3.max(Object.values(stats))]);
    // Compute the mean of frequencies
    const avg = d3.mean(Object.values(stats))];

    // Update the color of activities based on their frequency
    for (const [elementId, frequency] of Object.entries(stats)) {
        // isActivity is a function that returns true if elementId corresponds to an activity
        if (isActivity(elementId){
           const fillColor = colorScale(frequency);
           const fontColor = frequency > avg ? 'white' : 'default';

           bpmnVisualization.bpmnElementsRegistry.updateStyle(elementId,{
               fill: { color: fillColor },
               font: { color: fontColor }
           });
        }
    }
}
```

Below is a screenshot from the demo that displays the end result of these manipulations:

![Example of data-driven styling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yihoacugimooiit9l3nd.png)

<h1>Conclusion</h1>

That wraps up our overview of style management in _bpmn-visualization_. If you're interested in learning more or looking for some inspiration, feel free to check out our [bpmn-visualization-examples](https://github.com/process-analytics/bpmn-visualization-examples) repository on GitHub. Have fun on your learning journey! 

If you want to stay on top of the latest news and releases from the Process Analytics project, follow us through:


* Website:[ https://process-analytics.dev](https://process-analytics.dev/?utm_source=dev.to&utm_medium=display&utm_campaign=blog)
* Twitter:[ @ProcessAnalyti1](https://twitter.com/ProcessAnalyti1)
* GitHub:[ https://github.com/process-analytics](https://github.com/process-analytics)
* Discord:[ https://discord.com/invite/HafnBYsRXd](https://discord.com/invite/HafnBYsRXd)
* YouTube:[ Process Analytics YouTube channel](https://www.youtube.com/@process-analytics)