Skip to content
This is the alpha v4 version website. Looking for the v3 documentation?

Colors and sizes

Most of the time, people want to map node colors and sizes to graph attributes. You control the mapping between attributes and visual properties through styles.

The example below shows how to map some node categorical attribute to colors, and some node number attribute to sizes:

import Sigma from "sigma";
import { DEFAULT_STYLES } from "sigma/types";
import { getSmallGraph } from "../_data/small-graph";
const container = document.getElementById("sigma-container") as HTMLElement;
const graph = getSmallGraph();
const DATA: Record<string, { cluster: string; score: number }> = {
a: { cluster: "1", score: 0.0003 },
b: { cluster: "1", score: 0.0008 },
c: { cluster: "2", score: 0.0005 },
d: { cluster: "2", score: 0.0002 },
e: { cluster: "3", score: 0.001 },
f: { cluster: "3", score: 0.0004 },
};
graph.forEachNode((node) => {
graph.mergeNodeAttributes(node, DATA[node]);
});
new Sigma(graph, container, {
styles: {
nodes: [
DEFAULT_STYLES.nodes,
{
color: {
attribute: "cluster",
dict: { "1": "#E8684A", "2": "#5B8FF9", "3": "#61DDAA" },
defaultValue: "#999",
},
size: { attribute: "score", min: 10, max: 30, minValue: 0, maxValue: 0.001 },
},
],
edges: [DEFAULT_STYLES.edges],
},
});

Setting colors and sizes

The most common approach reads color and size directly from graph attributes (when they are stored “as is” in the graphology instance):

import Graph from "graphology";
import Sigma from "sigma";
const graph = new Graph();
graph.addNode("a", { x: 0, y: 0, size: 15, color: "#e22653", label: "Node A" });
graph.addNode("b", { x: 100, y: 100, size: 25, color: "#0055ff", label: "Node B" });
new Sigma(graph, container, {
styles: {
nodes: [{ color: { attribute: "color" }, size: { attribute: "size" } }],
},
});

You can also set fixed values that apply to all nodes:

styles: {
nodes: [
{ color: "#e22653", size: 10 },
],
}

Or mix fixed defaults with attribute overrides. Style rules are evaluated in order, and later values override earlier ones:

styles: {
nodes: [
{ color: "#cccccc", size: 10 },
{ color: { attribute: "color" }, size: { attribute: "size" } },
],
}

Conditional styles

You can change appearance based on node state. For example, grey out nodes that are not active:

styles: {
nodes: [
{ color: { attribute: "color" }, size: { attribute: "size" } },
{
when: (attrs, state, graphState) => graphState.hasActiveSubgraph && !state.isActive,
then: { color: "#f6f6f6" },
},
],
}

See Hover and search highlight for a full example of conditional styling.

Opacity and alpha blending

Use the opacity style property to control node and edge transparency:

import { layerBorder } from "@sigma/node-border";
import Graph from "graphology";
import Sigma from "sigma";
import { DEFAULT_STYLES } from "sigma/types";
import { registerControls } from "../_controls";
const container = document.getElementById("sigma-container") as HTMLElement;
const { bgColor, useColorAlpha, nodeOpacity, edgeOpacity, edgeSize } = registerControls({
bgColor: {
type: "select",
label: "Background",
default: "#ffffff",
options: [
{ label: "White", value: "#ffffff" },
{ label: "Light gray", value: "#e0e0e0" },
{ label: "Dark gray", value: "#333333" },
{ label: "Black", value: "#000000" },
],
},
useColorAlpha: { type: "boolean", label: "Use color alpha (not opacity)", default: false },
nodeOpacity: { type: "number", label: "Node opacity", default: 0.8, min: 0, max: 1, step: 0.05 },
edgeOpacity: { type: "number", label: "Edge opacity", default: 0.1, min: 0, max: 1, step: 0.05 },
edgeSize: { type: "number", label: "Edge size", default: 25, min: 0, max: 100, step: 2.5 },
});
container.style.backgroundColor = bgColor;
const isDarkBg = bgColor === "#333333" || bgColor === "#000000";
// Load data
const res = await fetch("/data/wikipedia.json");
const data: {
nodes: { key: string; label: string; cluster: string; x: number; y: number; score: number }[];
edges: [string, string][];
clusters: { key: string; color: string; clusterLabel: string }[];
} = await res.json();
// Build cluster color map
const clusterColors: Record<string, string> = {};
for (const c of data.clusters) {
clusterColors[c.key] = c.color;
}
// Brighten a hex color by mixing it with white
function brighten(hex: string, amount = 0.5): string {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
const mix = (c: number) => Math.round(c + (255 - c) * amount);
return `#${mix(r).toString(16).padStart(2, "0")}${mix(g).toString(16).padStart(2, "0")}${mix(b).toString(16).padStart(2, "0")}`;
}
// Convert hex color to rgba with given alpha
function withAlpha(hex: string, alpha: number): string {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
const graph = new Graph();
// Add nodes
for (const node of data.nodes) {
const color = clusterColors[node.cluster] || "#999";
const nodeColor = useColorAlpha ? withAlpha(color, nodeOpacity) : color;
const fillColor = brighten(color, 0.5);
graph.addNode(node.key, {
x: node.x,
y: node.y,
score: node.score,
label: node.label,
color: nodeColor,
fillColor: useColorAlpha ? withAlpha(fillColor, nodeOpacity) : fillColor,
});
}
// Add edges, colored by source node
for (const [source, target] of data.edges) {
if (graph.hasNode(source) && graph.hasNode(target)) {
const sourceColor = clusterColors[data.nodes.find((n) => n.key === source)?.cluster ?? ""] || "#999";
graph.addEdge(source, target, {
color: useColorAlpha ? withAlpha(sourceColor, edgeOpacity) : sourceColor,
});
}
}
new Sigma(graph, container, {
primitives: {
nodes: {
variables: {
fillColor: { type: "color", default: "#ccc" },
},
layers: [
layerBorder({
borders: [
{ size: 0.15, color: { attribute: "color" }, mode: "relative" },
{ size: 0, color: { attribute: "fillColor" }, fill: true },
],
}),
],
},
},
styles: {
nodes: [
DEFAULT_STYLES.nodes,
{
opacity: useColorAlpha ? 1 : nodeOpacity,
size: { attribute: "score", min: 25, max: 100, minValue: 0, maxValue: 0.1 },
...(isDarkBg ? { labelColor: { whenState: "isHovered", then: "#000", else: "#fff" } } : {}),
},
],
edges: [DEFAULT_STYLES.edges, { opacity: useColorAlpha ? 1 : edgeOpacity, size: edgeSize }],
},
});