CSS-like styling system with selectors, properties, and themes. Supports dynamic styling, animations, and complex visual customization for nodes, edges, and the core canvas.
Define styles using CSS-like syntax with selectors and property blocks.
interface StylesheetJson extends Array<StyleRule> {}
interface StyleRule {
/**
* CSS-like selector for targeting elements
*/
selector: string;
/**
* Style properties to apply
*/
style: StyleProperties;
}
/**
* Create stylesheet from array of style rules
*/
const stylesheet: StylesheetJson = [
{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc'
}
}
];Apply and manage styles on the core instance and collections.
interface Core {
/**
* Get or set stylesheet
* @param stylesheet - Stylesheet to apply (optional)
* @returns Current stylesheet or Core instance
*/
style(stylesheet?: StylesheetJson): StylesheetJson | Core;
/**
* Get stylesheet object
* @returns Stylesheet instance
*/
stylesheet(): Stylesheet;
/**
* Update style calculations (call after dynamic changes)
* @returns Core instance
*/
updateStyle(): Core;
}
interface Collection {
/**
* Get or set style property
* @param property - CSS property name
* @param value - Property value (optional)
* @returns Property value or Collection
*/
style(property: string, value?: any): any | Collection;
/**
* Get or set multiple style properties
* @param properties - Object with property-value pairs
* @returns Collection for chaining
*/
style(properties: StyleProperties): Collection;
/**
* Remove style properties (revert to stylesheet)
* @param properties - Properties to remove (optional, removes all if not specified)
* @returns Collection for chaining
*/
removeStyle(properties?: string | string[]): Collection;
}Target specific elements using CSS-like selectors.
/**
* Basic selectors
*/
"node" // All nodes
"edge" // All edges
"*" // All elements
/**
* ID selectors
*/
"#mynode" // Element with id 'mynode'
/**
* Class selectors
*/
".highlighted" // Elements with class 'highlighted'
".important.active" // Elements with both classes
/**
* Data selectors
*/
"[weight]" // Elements with 'weight' data property
"[weight > 10]" // Elements where weight > 10
"[type = 'user']" // Elements where type equals 'user'
"[name *= 'john']" // Elements where name contains 'john'
/**
* Compound selectors
*/
"node.active" // Active nodes
"edge[weight > 5]" // Heavy edges
"node#start.important" // Important start node
/**
* State selectors
*/
":selected" // Selected elements
":unselected" // Unselected elements
":locked" // Locked elements
":unlocked" // Unlocked elements
":grabbed" // Currently grabbed elements
":free" // Not grabbed elements
":removed" // Removed elements
":inside" // Elements inside compound nodes
":grabbable" // Grabbable elements
":ungrabbable" // Ungrabbable elements
/**
* Compound graph selectors
*/
":parent" // Parent (compound) nodes
":childless" // Nodes without children
":child" // Child nodes
":orphan" // Nodes without parents
/**
* Edge-specific selectors
*/
":simple" // Simple edges (no loops, no multiple edges)
":loop" // Self-loops
/**
* Combination selectors
*/
"node, edge" // Nodes OR edges (union)
"node.active edge" // Edges connected to active nodesUsage Examples:
// Style all nodes
const stylesheet = [
{
selector: 'node',
style: {
'background-color': '#0074D9',
'width': 20,
'height': 20,
'label': 'data(name)'
}
},
// Style selected nodes differently
{
selector: 'node:selected',
style: {
'background-color': '#FF4136',
'border-width': 3,
'border-color': '#FFDC00'
}
},
// Style edges by weight
{
selector: 'edge[weight > 5]',
style: {
'width': 4,
'line-color': '#FF851B'
}
}
];Comprehensive styling options for nodes.
interface NodeStyleProperties {
// Dimensions
'width'?: number | string;
'height'?: number | string;
'shape'?: 'ellipse' | 'triangle' | 'round-triangle' | 'rectangle' | 'round-rectangle' |
'bottom-round-rectangle' | 'cut-rectangle' | 'barrel' | 'rhomboid' | 'diamond' |
'round-diamond' | 'pentagon' | 'round-pentagon' | 'hexagon' | 'round-hexagon' |
'concave-hexagon' | 'heptagon' | 'round-heptagon' | 'octagon' | 'round-octagon' |
'star' | 'tag' | 'round-tag' | 'vee';
// Background
'background-color'?: string;
'background-opacity'?: number;
'background-blacken'?: number;
'background-image'?: string | string[];
'background-image-opacity'?: number | number[];
'background-fit'?: 'none' | 'contain' | 'cover';
'background-repeat'?: 'no-repeat' | 'repeat-x' | 'repeat-y' | 'repeat';
'background-position-x'?: string | number;
'background-position-y'?: string | number;
'background-width'?: string | number;
'background-height'?: string | number;
'background-clip'?: 'none' | 'node';
// Border
'border-width'?: number;
'border-style'?: 'solid' | 'dotted' | 'dashed' | 'double';
'border-color'?: string;
'border-opacity'?: number;
// Outline (selection indicator)
'outline-width'?: number;
'outline-color'?: string;
'outline-opacity'?: number;
'outline-offset'?: number;
// Padding (for compound nodes)
'padding'?: string | number;
'padding-left'?: string | number;
'padding-right'?: string | number;
'padding-top'?: string | number;
'padding-bottom'?: string | number;
// Compound node specific
'compound-sizing-wrt-labels'?: 'include' | 'exclude';
// Position
'position'?: 'origin';
// Visibility
'opacity'?: number;
'display'?: 'element' | 'none';
'visibility'?: 'visible' | 'hidden';
'z-index'?: number;
'z-compound-depth'?: 'bottom' | 'orphan' | 'auto' | number;
// Interactivity
'min-zoomed-font-size'?: number;
'overlay-color'?: string;
'overlay-padding'?: number;
'overlay-opacity'?: number;
'underlay-color'?: string;
'underlay-padding'?: number;
'underlay-opacity'?: number;
'underlay-shape'?: 'ellipse' | 'round-rectangle';
// Ghost (dragging preview)
'ghost'?: 'yes' | 'no';
'ghost-offset-y'?: number;
'ghost-offset-x'?: number;
'ghost-opacity'?: number;
}Styling options for edges including arrows, curves, and labels.
interface EdgeStyleProperties {
// Line
'width'?: number;
'line-color'?: string;
'line-style'?: 'solid' | 'dotted' | 'dashed';
'line-cap'?: 'butt' | 'round' | 'square';
'line-opacity'?: number;
'line-dash-pattern'?: number[];
'line-dash-offset'?: number;
// Curve
'curve-style'?: 'straight' | 'haystack' | 'bezier' | 'unbundled-bezier' |
'segments' | 'taxi' | 'round-taxi';
'control-point-step-size'?: number;
'control-point-distances'?: number | number[];
'control-point-weights'?: number | number[];
'segment-distances'?: number | number[];
'segment-weights'?: number | number[];
'taxi-turn'?: string;
'taxi-turn-min-distance'?: number;
'taxi-direction'?: 'auto' | 'up' | 'down' | 'left' | 'right' | 'downward' | 'upward' |
'leftward' | 'rightward' | 'vertical' | 'horizontal';
// Source arrow
'source-arrow-color'?: string;
'source-arrow-shape'?: 'triangle' | 'triangle-tee' | 'circle-triangle' | 'triangle-cross' |
'triangle-backcurve' | 'vee' | 'tee' | 'square' | 'circle' |
'diamond' | 'chevron' | 'none';
'source-arrow-width'?: number;
'source-arrow-height'?: number;
// Target arrow
'target-arrow-color'?: string;
'target-arrow-shape'?: 'triangle' | 'triangle-tee' | 'circle-triangle' | 'triangle-cross' |
'triangle-backcurve' | 'vee' | 'tee' | 'square' | 'circle' |
'diamond' | 'chevron' | 'none';
'target-arrow-width'?: number;
'target-arrow-height'?: number;
// Mid arrow
'mid-source-arrow-color'?: string;
'mid-source-arrow-shape'?: string;
'mid-source-arrow-width'?: number;
'mid-source-arrow-height'?: number;
'mid-target-arrow-color'?: string;
'mid-target-arrow-shape'?: string;
'mid-target-arrow-width'?: number;
'mid-target-arrow-height'?: number;
// Visibility and interaction
'opacity'?: number;
'display'?: 'element' | 'none';
'visibility'?: 'visible' | 'hidden';
'z-index'?: number;
'overlay-color'?: string;
'overlay-padding'?: number;
'overlay-opacity'?: number;
'underlay-color'?: string;
'underlay-padding'?: number;
'underlay-opacity'?: number;
// Selection
'selection-box-color'?: string;
'selection-box-border-color'?: string;
'selection-box-border-width'?: number;
'selection-box-opacity'?: number;
// Loop edges
'loop-direction'?: string;
'loop-sweep'?: string;
// Haystack edges
'haystack-radius'?: number;
// Ghost
'ghost'?: 'yes' | 'no';
'ghost-offset-y'?: number;
'ghost-offset-x'?: number;
'ghost-opacity'?: number;
}Text labels for nodes and edges with extensive typography control.
interface LabelStyleProperties {
// Content
'label'?: string;
// Typography
'color'?: string;
'font-family'?: string;
'font-size'?: number | string;
'font-style'?: 'normal' | 'italic' | 'oblique';
'font-variant'?: 'normal' | 'small-caps';
'font-weight'?: 'normal' | 'bold' | 'bolder' | 'lighter' | number;
'text-transform'?: 'none' | 'uppercase' | 'lowercase' 'capitalize';
// Alignment
'text-halign'?: 'left' | 'center' | 'right';
'text-valign'?: 'top' | 'center' | 'bottom';
// Positioning
'text-margin-x'?: number;
'text-margin-y'?: number;
'text-rotation'?: number | 'autorotate' | 'none';
// Wrapping
'text-wrap'?: 'none' | 'wrap' | 'ellipsis';
'text-max-width'?: number | string;
'text-overflow-wrap'?: 'whitespace' | 'anywhere';
'text-justification'?: 'left' | 'center' | 'right' | 'auto';
// Background
'text-background-color'?: string;
'text-background-opacity'?: number;
'text-background-shape'?: 'rectangle' | 'round-rectangle';
'text-background-padding'?: number;
// Border
'text-border-color'?: string;
'text-border-width'?: number;
'text-border-style'?: 'solid' | 'dotted' | 'dashed' | 'double';
'text-border-opacity'?: number;
// Outline
'text-outline-color'?: string;
'text-outline-width'?: number;
'text-outline-opacity'?: number;
// Shadow
'text-shadow-blur'?: number;
'text-shadow-color'?: string;
'text-shadow-offset-x'?: number;
'text-shadow-offset-y'?: number;
'text-shadow-opacity'?: number;
// Visibility
'text-opacity'?: number;
'min-zoomed-font-size'?: number;
// Edge label positioning
'source-text-offset'?: number;
'target-text-offset'?: number;
'source-text-rotation'?: number | 'autorotate';
'target-text-rotation'?: number | 'autorotate';
}Styling for the core canvas and global elements.
interface CoreStyleProperties {
// Background
'background-color'?: string;
'background-opacity'?: number;
'background-image'?: string;
'background-fit'?: 'none' | 'contain' | 'cover';
'background-repeat'?: 'no-repeat' | 'repeat-x' | 'repeat-y' | 'repeat';
'background-position-x'?: string | number;
'background-position-y'?: string | number;
'background-width'?: string | number;
'background-height'?: string | number;
// Selection box
'selection-box-color'?: string;
'selection-box-border-color'?: string;
'selection-box-border-width'?: number;
'selection-box-opacity'?: number;
// Active background (when panning/zooming)
'active-bg-color'?: string;
'active-bg-opacity'?: number;
'active-bg-size'?: number;
// Outside texture (for very large graphs)
'outside-texture-bg-color'?: string;
'outside-texture-bg-opacity'?: number;
}Apply styles programmatically and respond to data changes.
/**
* Data-driven styling using mappers
*/
// Map data to style values
const stylesheet = [
{
selector: 'node',
style: {
'width': 'mapData(weight, 0, 100, 10, 50)',
'height': 'mapData(weight, 0, 100, 10, 50)',
'background-color': 'mapData(score, 0, 1, blue, red)'
}
}
];
// Conditional styling
const conditionalStyle = [
{
selector: 'node[type = "user"]',
style: {
'shape': 'round-rectangle',
'background-color': '#3498db'
}
},
{
selector: 'node[type = "group"]',
style: {
'shape': 'hexagon',
'background-color': '#e74c3c'
}
}
];
// Style based on degree
cy.nodes().forEach(node => {
const degree = node.degree();
node.style({
'width': Math.max(20, degree * 5),
'height': Math.max(20, degree * 5),
'background-color': degree > 3 ? 'red' : 'blue'
});
});Manage CSS classes for reusable styling patterns.
interface Collection {
/**
* Add CSS classes to elements
* @param classes - Space-separated class names
* @returns Collection for chaining
*/
addClass(classes: string): Collection;
/**
* Remove CSS classes from elements
* @param classes - Space-separated class names (optional, removes all if not specified)
* @returns Collection for chaining
*/
removeClass(classes?: string): Collection;
/**
* Toggle CSS classes on elements
* @param classes - Space-separated class names
* @param state - Force toggle state (optional)
* @returns Collection for chaining
*/
toggleClass(classes: string, state?: boolean): Collection;
/**
* Check if elements have CSS class
* @param className - Class name to check
* @returns True if all elements have the class
*/
hasClass(className: string): boolean;
/**
* Get all classes on first element
* @returns Array of class names
*/
classes(): string[];
}Usage Examples:
// Define classes in stylesheet
const stylesheet = [
{
selector: '.highlighted',
style: {
'background-color': 'yellow',
'border-width': 3,
'border-color': 'orange'
}
},
{
selector: '.faded',
style: {
'opacity': 0.3
}
}
];
// Apply classes dynamically
cy.nodes().addClass('highlighted');
cy.edges().addClass('faded');
// Toggle classes based on selection
cy.on('select', 'node', function(evt) {
evt.target.addClass('selected');
});
cy.on('unselect', 'node', function(evt) {
evt.target.removeClass('selected');
});Animate style changes for smooth visual transitions.
interface Collection {
/**
* Animate style changes
* @param properties - Style properties to animate
* @param options - Animation options
* @returns Promise that resolves when animation completes
*/
animate(properties: StyleProperties, options?: AnimationOptions): Promise<Collection>;
}
interface AnimationOptions {
/**
* Animation duration in milliseconds
*/
duration?: number;
/**
* Easing function
*/
easing?: string;
/**
* Delay before animation starts
*/
delay?: number;
/**
* Callback when animation completes
*/
complete?: () => void;
/**
* Callback for each animation step
*/
step?: (now: number, tween: any) => void;
/**
* Animation queue name
*/
queue?: string | boolean;
}Usage Examples:
// Animate node color change
node.animate({
'background-color': 'red',
'width': 50,
'height': 50
}, {
duration: 1000,
easing: 'ease-in-out'
});
// Chain animations
node.animate({
'background-color': 'blue'
}, 500).then(() => {
return node.animate({
'background-color': 'green'
}, 500);
});
// Animate multiple properties
cy.nodes().animate({
'background-color': 'purple',
'width': 'mapData(degree, 0, 10, 20, 60)'
}, {
duration: 2000,
complete: () => console.log('Animation finished')
});Helper functions and advanced styling techniques.
/**
* Style utility functions
*/
// Get computed style value
const computedColor = node.style('background-color');
const computedWidth = node.style('width');
// Check if style is applied
const hasCustomColor = node.style('background-color') !== node.removeClass().style('background-color');
// Reset styles to stylesheet defaults
node.removeStyle();
node.removeStyle(['background-color', 'width']);
// Batch style operations for performance
cy.batch(() => {
cy.nodes().style('background-color', 'blue');
cy.edges().style('line-color', 'red');
});
// Style templates
function applyNodeTemplate(nodes, template) {
nodes.style(template);
}
applyNodeTemplate(cy.nodes('.important'), {
'background-color': '#ff6b6b',
'border-width': 3,
'border-color': '#4ecdc4'
});