Vis.js Fundamentals and Node Styling
Summary
Introduces vis.js and the vis-network library as the primary tool for visualizing concept dependency graphs, covering DataSet, network initialization, and the full range of node visual properties (shape, color, size, icons, images, shadows).
Concepts Covered
This chapter covers the following 19 concepts from the learning graph:
- Vis.js
- Vis-Network Library
- DataSet
- Network Container
- Network Initialization
- JSON Data Format
- Force-Directed Graph
- Legend Display
- Node Shape
- Node Background Color
- Node Size
- Node Font Color
- Node Border Width
- Node Border Color
- Node Opacity
- Node Icon
- Node Image
- Node Shadow
- Custom Canvas Shape
Prerequisites
This chapter builds on concepts from:
Welcome to Part III!
Let's connect the concepts! Every diagram you have clicked, hovered, and dragged through so far in this book was built with a specific JavaScript library — and starting now, you get to look under the hood. Part III is where the vocabulary of graphs meets actual code you can read, copy, and modify.
Everything up to this point in the book has treated a learning graph as an abstract structure: nodes, edges, dependency direction, validation rules, file formats. That abstraction was necessary, but abstractions do not help a learner see forty concepts and their prerequisite relationships at once. This chapter opens Part III, where the book shifts from theory to hands-on tooling — starting with the JavaScript library that renders every interactive graph diagram you have already clicked through in earlier chapters.
What Is Vis.js?
Vis.js is a browser-based JavaScript visualization library for displaying dynamic, interactive data — networks, timelines, charts, and 3D graphs — directly in a web page with no server-side rendering required. It is not a single tool but a family of related components, each specialized for a different data shape: vis-timeline for chronological events, vis-graph3d for three-dimensional plots, and, most importantly for this book, vis-network for exactly the kind of node-and-edge structure a learning graph is.
The Vis-Network Library is the specific component of vis.js used to draw and interact with graphs made of nodes and edges — the component behind every diagram in this book so far, including the Graph Anatomy Explorer in Chapter 1 and the Orphan and Disconnected Subgraph Explorer in Chapter 5. Vis-network handles the parts of graph rendering that are tedious to build from scratch: physics-based layout, zooming and panning, click and hover event handling, and a large set of visual styling options for both nodes and edges. This chapter and the next several focus entirely on vis-network, because it is the single tool a learning-graph author needs to master in order to visualize, edit, and publish concept dependency graphs.
Helpful Tip
You do not need to be a JavaScript expert to use vis-network productively. Most of the work is describing data — which nodes exist, which edges connect them, and what each should look like — in a format vis-network already understands. The library does the hard part: physics, rendering, and interaction.
Loading Graph Data: DataSet and JSON
Before vis-network can draw anything, it needs the node and edge data organized in a structure it can efficiently read, update, and re-render. That structure is called a DataSet.
A DataSet is a vis.js data container that holds a collection of JavaScript objects — nodes or edges — and gives vis-network fast, reactive access to them: when an item in a DataSet changes, any network displaying that DataSet updates automatically, without the developer manually re-drawing the canvas. You will create one DataSet for your nodes and a second DataSet for your edges, then hand both to the network object described in the next section.
You already know the file format that feeds a DataSet, because Chapter 5 covered it in detail. The JSON Data Format is the JavaScript Object Notation structure used to store vis-network's node and edge arrays — each node is a JSON object with at minimum an id and a label field, and each edge is a JSON object with a from field and a to field pointing at two node IDs. This is the same learning-graph.json file structure you have seen throughout this book; vis-network is simply the tool that turns that file into a picture.
The following short example shows the minimum code needed to load a JSON file and wrap its contents in two DataSets. Read it as three steps: fetch the file, wrap the arrays in vis.DataSet, and hand the pair to the network (covered in the next section). The fetch() call retrieves the JSON file asynchronously; .then(response => response.json()) parses the raw text into a JavaScript object; and new vis.DataSet(data.nodes) wraps the resulting nodes array so vis-network can track it reactively.
1 2 3 4 5 6 7 8 9 10 | |
The Network Container and Network Initialization
A DataSet holds data, but data alone is invisible. Vis-network needs a place on the page to draw into, and an explicit instruction to start drawing.
The Network Container is the HTML element — almost always a <div> — that vis-network uses as the drawing surface for a graph. It must exist in the page's HTML before the JavaScript runs, and it must have a defined height (vis-network cannot compute its own height from empty content the way text elements can). A typical container looks like <div id="mynetwork"></div>, styled with CSS to a fixed or responsive height.
Network Initialization is the act of constructing a new vis.Network(container, data, options) object, which is the single line of code that actually renders the graph — combining the container element, the node/edge DataSets, and a configuration object into a live, interactive visualization. Once this line runs, vis-network takes over: it lays out the nodes, draws the edges, and starts listening for mouse events.
Building on the fetch example above, the code below completes the pattern by grabbing the container element, bundling the two DataSets into a data object, and calling new vis.Network(). The options object is left empty here ({}) — later sections of this chapter fill it with node styling instructions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
This four-part pattern — fetch, DataSet, container, initialize — is the skeleton underneath every vis-network visualization in this book. Every remaining topic in this chapter is about what goes inside the options object or inside each node's JSON, not about changing this skeleton.
How Nodes Find Their Positions: The Force-Directed Graph
Notice that the JSON data above never specifies where each node should sit on the screen — no x/y coordinates. Vis-network still manages to lay the graph out sensibly, and the reason is its default layout algorithm.
A Force-Directed Graph is a graph layout technique that treats nodes as physical objects: edges act like springs pulling connected nodes together, while all nodes simultaneously repel each other like magnets with the same polarity. The layout "settles" into a stable arrangement where these opposing forces balance out — densely connected nodes cluster near each other, while loosely connected nodes drift toward the edges of the canvas. This is the layout style used by default in vis-network, and it is the reason the Structural Variations Explorer in Chapter 1 could offer a "Cluster View" without any manually assigned coordinates.
Force-directed layout is popular for concept dependency graphs precisely because it requires no manual positioning: add a new concept and a new edge to the JSON, and the physics simulation re-settles the whole graph to accommodate it. The trade-off, which later chapters in Part III return to, is that force-directed layouts can look chaotic for very large graphs and don't guarantee a clean top-to-bottom prerequisite ordering the way a hierarchical layout does.
Before you experiment with the MicroSim below, hold onto one more idea: every node in that MicroSim is still using vis-network's default circular shape with no custom styling — the rest of this chapter changes that, one property at a time.
Diagram: Force-Directed Layout Explorer
View Force-Directed Layout Explorer Fullscreen
Force-Directed Layout Explorer
Type: microsim
sim-id: force-directed-layout-explorer
Library: vis-network
Status: Specified
Purpose: Let learners manipulate the physics parameters of a force-directed layout and observe how spring strength and repulsion change the resting shape of a graph.
Bloom Level: Apply (L3) Bloom Verb: demonstrate, experiment
Learning objective: Given a small graph and adjustable physics sliders, the learner can predict and observe how increasing repulsion spreads nodes apart and how increasing spring (edge) strength pulls connected nodes closer together.
Canvas layout: - Left/top (75% width): drawing area showing a 14-node sample graph drawn from this chapter's own concept list (Vis.js, Vis-Network Library, DataSet, Network Container, Network Initialization, JSON Data Format, Force-Directed Graph, and 7 more) - Right/bottom (25% width or below on narrow screens): control panel
Visual elements: - 14 light-blue circular nodes with black text labels - Directed gray edges (dependency direction, arrowhead at prerequisite end) - A "settling" indicator (small spinner) that appears while physics is still animating and disappears once the layout stabilizes
Interactive controls:
- Slider: "Repulsion Strength" (range -20000 to -1000, default -8000) — maps to vis-network's physics.barnesHut.gravitationalConstant
- Slider: "Spring Length" (range 50 to 300, default 150) — maps to physics.barnesHut.springLength
- Slider: "Spring Strength" (range 0.01 to 0.5, default 0.08) — maps to physics.barnesHut.springConstant
- Button: "Re-Settle Graph" — nudges the physics simulation to re-run from the current node positions
- Button: "Reset to Defaults"
Default parameters: - Repulsion Strength: -8000 - Spring Length: 150 - Spring Strength: 0.08
Behavior: Moving any slider calls network.setOptions() with the updated physics configuration and re-enables the physics simulation briefly so the graph visibly re-settles into its new resting shape. An infobox below the sliders states in one sentence what changed, e.g., "Higher repulsion pushes nodes further apart, spreading the graph out."
Canvas size: responsive, 100% width, 540px height, must reflow on window resize
Implementation: vis-network JavaScript library using the physics.barnesHut solver options exposed through network.setOptions(); slider input events trigger option updates
The Node Property Toolbox: An Overview
Every node in a vis-network JSON file can carry an entire set of visual styling properties beyond just an id and a label. Before diving into each property individually, it helps to see them together as a toolbox, because in practice a learning-graph author combines several of these properties at once to make a diagram's visual encoding meaningful — for instance, using color to represent a taxonomy category (as Chapter 4 covered) while using shape to represent a concept's role (foundation, term, or goal).
The table below organizes the properties this chapter covers. Each row is explained in its own section afterward — treat the table as a map of what's coming, not as your first introduction to any of these terms.
| Property | JSON Key | What It Controls |
|---|---|---|
| Node Shape | shape |
The geometric outline used to draw the node |
| Node Background Color | color.background |
The fill color inside the node's shape |
| Node Size | size |
The radius (in pixels) of shapes without an inline label |
| Node Font Color | font.color |
The color of the node's label text |
| Node Border Width | borderWidth |
The thickness, in pixels, of the node's outline |
| Node Border Color | color.border |
The color of the node's outline |
| Node Opacity | opacity |
How transparent or solid the node appears |
| Node Icon | icon |
A font-based symbol (e.g., FontAwesome) drawn inside the node |
| Node Image | image |
A raster or vector image file used as the node's shape |
| Node Shadow | shadow |
A drop-shadow effect behind the node |
| Custom Canvas Shape | shape: "custom" |
A developer-defined drawing function replacing all built-in shapes |
Node Shape
The Node Shape property controls the geometric outline vis-network uses to draw a node — the most immediately visible styling choice, and usually the first one a learning-graph author sets. Vis-network ships with a substantial built-in library of shapes, split into two behavioral categories that matter for later properties in this chapter.
Some shapes draw the label text inside the shape, sizing the shape to fit the text automatically: box, ellipse, circle, and database all behave this way. Other shapes draw the label below a fixed-size icon or outline, and their visual size is controlled entirely by the Node Size property covered next: image, circularImage, diamond, dot, star, triangle, triangleDown, hexagon, square, and icon. Knowing which category a shape falls into matters because setting size on a box node does nothing — the box already sizes itself to the label — while setting size on a dot node is the only way to make it bigger or smaller.
circle— a fixed circular outline with the label inside; label may be clipped if too longbox— a rectangle sized to fit the label, with configurable rounded cornersellipse— the vis-network default shape; an oval sized to fit the labeldiamond— a fixed-size diamond outline, label drawn belowstar— a five-point star, label drawn belowtriangle/triangleDown— pointing up or down respectively, label drawn belowdot— a simple filled circle, label drawn belowsquare/hexagon— regular polygons, label drawn belowdatabase— a cylinder shape evoking a data store, label insidetext— no visible outline at all, only the label text
Setting a node's shape in the JSON is a single key-value pair. The shape field accepts any of the string values listed above:
1 2 3 4 5 | |
Node Background Color and Node Font Color
Shape gives a node its outline; color gives it meaning at a glance. Two related properties control color, and it is worth learning them together because a common mistake — dark background with dark text — only becomes visible once both are set.
Node Background Color is the fill color inside a node's shape, set through the color property in the node's JSON. Vis-network accepts either a simple color name string ("color": "red") or, for finer control, an object that separately specifies the background and border colors ("color": {"background": "red", "border": "black"}). Background color is the single most common visual encoding in a learning graph diagram — Chapter 4 used it to distinguish taxonomy categories, and Chapter 1's diagrams used it to distinguish node states (valid vs. cycle-forming, for example).
Node Font Color is the color of the text label drawn on or below a node, set through the nested font.color property ("font": {"color": "white"}). The default font color in vis-network is black, which reads clearly on light backgrounds like gold, orange, or pale blue — but becomes nearly illegible on dark backgrounds like green, purple, or navy. Whenever a background color falls on the darker half of the color spectrum, pair it with an explicit white font color.
The example below extends the shape example from the previous section, adding background colors to every node and white font color specifically on the two darkest nodes:
1 2 3 4 5 6 | |
Watch Out
Purple and green nodes with black text are a genuinely common accessibility mistake in early graph diagrams. If you can't read a label at a glance while zoomed to a normal level, neither can your students — fix the font color before you move on to any other styling.
Node Size
Recall from the Node Shape discussion that some shapes size themselves to their label text, while others — dot, star, diamond, triangle, square, hexagon, icon, image, and circularImage — use a fixed size that must be set explicitly. The Node Size property, set through the size key, controls the radius in pixels of exactly this second category of shapes.
Node size is also a common encoding for a quantitative property of a concept — degree (the number of connections a node has, covered in Chapter 5) is a frequent choice, since a concept many other concepts depend on visually "reads" as more important when drawn larger. The Structural Variations Explorer's hover badge in Chapter 1, which displayed a node's degree on hover, pairs naturally with a diagram that also scales node size to that same degree value.
1 | |
Note that this example sets size on a box-shaped node — which, per the rule above, has no visible effect, since box sizes itself to its label. This is a common early mistake: setting size on a label-sized shape produces no visual change, which can look like a bug when it is really a mismatched shape choice.
Node Border Width and Node Border Color
Fill color and font color handle the interior of a node; two more properties control its outline.
Node Border Width is the thickness, measured in pixels, of the line drawn around a node's shape, set through the borderWidth key (default 1). Increasing border width is a lightweight way to draw attention to a specific node — a selected node, a node currently in violation of a validation rule, or a node representing the current step in a journey map — without changing its size or color.
Node Border Color is the color of that outline, set through the nested color.border key when color is expressed as an object rather than a single string ("color": {"background": "lightblue", "border": "darkblue"}). Border color and background color are independent: a node can have a light background with a dark, high-contrast border, which is often more readable than a uniformly dark node with white text.
Building on Chapter 1's Graph Anatomy Explorer, which used "highlighted gold with a thicker gold border" to mark a selected node, the JSON snippet below shows how that selected-state styling is expressed:
1 2 3 4 5 6 | |
Node Opacity
The Node Opacity property controls how transparent or solid a node appears, set through the opacity key as a decimal between 0 (fully transparent, effectively invisible) and 1 (fully solid, the default). Opacity is most useful as a state indicator rather than a permanent styling choice — dimming nodes that are not currently relevant while keeping the highlighted subset at full opacity. The Journey Map Builder MicroSim from Chapter 1 used exactly this technique, described as "dimming nodes/edges not on the chosen path," to focus attention on one derived route through a larger graph.
1 | |
Because opacity is usually applied dynamically — in response to a click, a filter, or a lens selection — rather than baked permanently into a JSON file, it is more often set in JavaScript through nodes.update({id: 7, opacity: 0.3}) than written directly into the static data file.
Node Icon and Node Image
Shapes and colors communicate a lot, but sometimes the clearest way to represent a concept is a small recognizable symbol or picture. Vis-network supports two distinct approaches, and it is worth understanding the difference before choosing between them.
A Node Icon is a font-based symbol — typically drawn from an icon font library such as FontAwesome — rendered inside a node using the shape: "icon" setting together with an icon configuration object specifying the font face, the character code, the size, and the color. Icons are vector-based, so they stay crisp at any zoom level and can be recolored on the fly, which makes them a good fit for representing a small, fixed set of concept types (a book icon for reading material, a gear icon for a tool or process, a lightbulb icon for a key insight).
A Node Image is a raster or vector picture file — PNG, JPG, or SVG — used as the node's entire visual shape, set through shape: "image" (a rectangular image) or shape: "circularImage" (the same image cropped to a circle) together with an image field pointing at the file's URL. Images are the right choice when a concept is best represented by an actual photograph, diagram thumbnail, or custom illustration rather than a symbolic icon — a portrait node for a historical figure in the Stories section of a textbook, for instance, or a screenshot thumbnail representing a specific piece of content.
The following table summarizes when each is the better fit, now that both have been explained in prose:
| Situation | Better Choice | Why |
|---|---|---|
| Representing a category (tool, concept, process) | Node Icon | Scales cleanly, easy to recolor, small file footprint |
| Representing a specific real-world thing (a person, a screenshot) | Node Image | Preserves actual visual detail an icon cannot convey |
| Diagram will be zoomed in and out frequently | Node Icon | Vector icons stay sharp; raster images can blur |
| Large graph with hundreds of nodes | Node Icon | Icon fonts load faster than hundreds of image files |
1 2 3 4 5 6 7 8 9 10 11 12 | |
Node Shadow
The Node Shadow property adds a drop-shadow effect behind a node, set through the shadow key — either a simple boolean ("shadow": true for a default gray shadow) or an object specifying the shadow's color, blur radius, and x/y offset ("shadow": {"enabled": true, "color": "rgba(0,0,0,0.5)", "size": 10, "x": 5, "y": 5}). Shadow is a subtle effect compared to shape, color, or size, but it is useful for creating a visual sense of depth — making a currently-selected or currently-hovered node appear to "lift" off the canvas relative to its neighbors.
1 | |
Legend Display
With eleven different node styling properties available, a diagram with a dozen or more nodes quickly needs a way to explain its own visual encoding to the reader — otherwise color and shape become decoration rather than information. Legend Display is the practice of rendering a key alongside a vis-network diagram that maps each visual encoding (a color, a shape, an icon) back to the category or meaning it represents, typically implemented as a small set of extra non-interactive nodes positioned in a fixed corner of the canvas, or as an HTML panel built alongside the network container.
A well-built legend does three things: it lists every distinct color, shape, or icon actually used in the diagram (not a generic reference list); it labels each with the plain-language category it stands for; and — per this book's interactivity standard — it responds to learner interaction rather than sitting inert. The MicroSim below demonstrates a clickable legend built on top of the taxonomy-colored nodes from Chapter 4, letting a learner toggle entire categories on and off.
Before exploring the MicroSim, note the key interaction pattern: clicking a legend entry doesn't just highlight it — it filters the DataSet, hiding every node that doesn't match the selected category, which is a different (and more powerful) interaction than a legend that merely displays.
Diagram: Interactive Legend Filter
View Interactive Legend Filter Fullscreen
Interactive Legend Filter
Type: microsim
sim-id: interactive-legend-filter
Library: vis-network
Status: Specified
Purpose: Teach learners that a legend in an intelligent textbook diagram is not a static caption but a functional filter control tied to the underlying DataSet.
Bloom Level: Apply (L3) Bloom Verb: demonstrate, use
Learning objective: Given a graph with nodes colored by taxonomy category, the learner can use a clickable legend to filter the visible node set and explain how the legend's colors map to the DataSet's category field.
Canvas layout: - Top (80% height): drawing area with a 20-node sample graph, nodes colored by one of four taxonomy categories drawn from Chapter 4 (Foundational Concepts = blue, Graph Theory = green, Visualization = gold, Learning Science = purple) - Bottom (20% height) or right sidebar on wide screens: legend panel with four clickable color swatches, each labeled with its category name and a live count of visible nodes in that category
Visual elements: - 20 circular nodes colored by category as listed above - Directed gray edges - Legend swatches: colored square, category label, node count badge (e.g., "Graph Theory (6)") - A "Show All" reset link above the legend
Interactive controls: - Click a legend swatch: toggles that category's visibility; hidden categories show the swatch at reduced opacity and gray out the count badge - Multiple categories may be toggled off simultaneously - Hover a legend swatch (without clicking): temporarily highlights that category's nodes in the graph with a gold outline, without hiding others - "Show All" link: restores all four categories to visible
Behavior: Clicking a swatch calls nodes.update() to set hidden: true on every node in that category's DataSet subset, then calls network.redraw(). The node count badge recalculates from the live DataSet on every toggle.
Canvas size: responsive, 100% width, 560px height, must reflow on window resize
Implementation: vis-network JavaScript library; legend built as an HTML/CSS panel outside the canvas, wired to DataSet filter operations via nodes.getIds({filter: ...})
Key Insight
A legend that only displays meaning is documentation. A legend that also filters the graph is a study tool — it lets a learner isolate one taxonomy category at a time and ask, "what does just the Graph Theory cluster look like on its own?" That shift, from passive caption to interactive control, is the theme of everything Part III builds toward.
Custom Canvas Shape
Every property covered so far configures one of vis-network's built-in shapes. But sometimes none of them — box, star, diamond, icon, image — is the right fit for what a concept needs to communicate visually. Vis-network provides an escape hatch for exactly this situation.
A Custom Canvas Shape is a node shape defined by the developer's own drawing function rather than selected from vis-network's built-in list, enabled by setting shape: "custom" and supplying a ctxRenderer function that receives the browser's HTML5 Canvas 2D drawing context and draws whatever the developer specifies — an arbitrary polygon, a mini bar chart, a progress ring, or any shape composed from basic drawing primitives (arcs, lines, fills). This is the most powerful and most complex node styling option in vis-network, because it trades the simplicity of a JSON property for full programmatic control.
Because a custom canvas shape depends on the HTML5 Canvas API rather than a simple property value, it cannot be expressed in a single line of JSON the way shape: "star" can. Instead, the node's JSON sets shape: "custom" and points at a JavaScript function supplied separately in the network options:
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Custom canvas shapes are rare in ordinary concept dependency graph diagrams — most learning-graph visualization needs are met by the built-in shape, color, size, icon, and image properties covered earlier in this chapter. Reach for a custom shape only when the visualization needs to encode information no built-in property can express, such as a live progress ring, a sparkline, or a shape that changes based on real-time data rather than a fixed category.
The MicroSim below lets you compare every node styling property covered in this chapter side by side, so you can see how shape, color, size, border, opacity, icon, image, and shadow combine on the same underlying data.
Diagram: Node Styling Property Playground
View Node Styling Property Playground Fullscreen
Node Styling Property Playground
Type: microsim
sim-id: node-styling-property-playground
Library: vis-network
Status: Specified
Purpose: Let learners apply each node styling property from this chapter to a single sample node in real time and observe the resulting JSON alongside the rendered result.
Bloom Level: Apply (L3) Bloom Verb: apply, experiment, demonstrate
Learning objective: Given a control panel exposing every node styling property covered in this chapter, the learner can construct a fully styled node and correctly match each visual change to its corresponding JSON property.
Canvas layout: - Left (55% width): drawing area showing one large sample node plus two unstyled neighbor nodes for visual context - Right (45% width): control panel, stacked vertically; on narrow screens, control panel moves below the canvas
Visual elements: - One centered sample node, initial state: default ellipse, light blue, black text, borderWidth 1 - Two smaller unstyled neighbor nodes connected by edges, for scale reference - A read-only JSON preview panel beneath the controls, live-updating to show the exact node JSON the current control settings produce
Interactive controls: - Dropdown: Node Shape (circle, box, ellipse, diamond, star, triangle, dot, square, hexagon, icon, image) - Color picker: Background Color - Color picker: Font Color - Slider: Size (10-80px, only active/visible when shape is in the fixed-size category) - Slider: Border Width (0-10px) - Color picker: Border Color - Slider: Opacity (0.0-1.0) - Checkbox: Enable Shadow - Dropdown: Icon (FontAwesome sample set of 6 icons, only active when shape is "icon") - Text input: Image URL (only active when shape is "image" or "circularImage")
Default parameters: - Shape: ellipse, Background: lightblue, Font: black, Size: 25, Border Width: 1, Border Color: darkblue, Opacity: 1.0, Shadow: off
Behavior: Every control change calls nodes.update() on the sample node's DataSet entry with the new property value and refreshes the JSON preview panel to show the resulting object. Controls that don't apply to the current shape (e.g., Size for a box shape) are visually disabled with an explanatory tooltip.
Canvas size: responsive, 100% width, 580px height, must reflow on window resize
Implementation: vis-network JavaScript library; control panel built with standard HTML form elements; JSON preview generated with JSON.stringify(nodes.get(sampleNodeId), null, 2)
Key Takeaways
- Vis.js is a family of browser-based visualization libraries; the Vis-Network Library is the component used to render node-and-edge graphs like concept dependency graphs.
- A DataSet is vis-network's reactive container for nodes and edges, populated from the JSON Data Format already familiar from Chapter 5.
- A Network Container (an HTML element) plus Network Initialization (
new vis.Network(container, data, options)) is the minimum code needed to render any graph. - The default Force-Directed Graph layout uses spring-and-repulsion physics to position nodes without manual coordinates.
- Eleven node styling properties — Shape, Background Color, Size, Font Color, Border Width, Border Color, Opacity, Icon, Image, Shadow, and Custom Canvas Shape — give an author full control over what each node communicates visually.
- Legend Display turns a styled diagram's color and shape choices into readable, and ideally interactive, meaning for the learner.
Well Done!
Pause and appreciate your progress — you just went from reading graph diagrams to understanding exactly how they are built, property by property. Next up: edges get the same treatment, from arrow styles to dashed lines to hover labels. Let's connect the concepts!