NavigationFree

Connected Nodes

Four color-coded nodes positioned with CSS and connected by an SVG overlay — the ready-to-wire HTML/CSS foundation for any interactive graph or dependency map.

SVGJSDrag
A
B
C
D
Hover or click the scene to interact

This effect is free — the Navigation category contains 36 effects total, including 4 free. Effect.Labs has 811 vanilla effects. Explore the category →

Usage examples

Service topology 4 services live
4 services 4 active connections Drag a node to explore

① Dashboard — Microservice topology map

WhenIn a monitoring or architecture panel to display dependencies between services (API, database, cache, message queue) without loading a third-party graph library.
WhyThe SVG + CSS structure is enough for a static graph; the drag JS adds exploratory interactivity on demand. Dark background and domain-coded colors convey service type at a glance.
SettingsDefault CSS percentage positions kept, stroke-width: 2, stroke-dasharray: 6 4, 48 px nodes, default palette (indigo API, pink DB, green Cache, amber Queue).
My workspace Concept map — Article

② Content editor — Article concept map

WhenIn a writing tool or wiki to visualize an article's structure (concepts, sections, themes) and links between ideas before drafting, with a central pivot node.
WhyA hub-and-spoke topology (one central node connected to the others) naturally models a mind map; dashed SVG lines stay readable on light or dark backgrounds without cluttering the interface.
SettingsHub node centered (top: 40%, left: 40%), stroke-width: 1 for a lighter look, short labels (4–5 chars max), colors aligned to the editorial brand.
Data pipeline

③ Low-code tool — Data processing pipeline editor

WhenIn a no-code interface where users visually connect processing blocks (Source → Filter → Transform → Output) by drag-and-drop linking.
WhyNodes and SVG lines are the UI primitive of any workflow editor; updating SVG coordinates on drag is native to the DOM — no canvas or third-party library required.
Settings4 nodes arranged diagonally, linear connections (a→b→c→d, no return d→a), short labels for processing steps (SRC, MAP, FLT, OUT).

How it works

Each node is a <div class="node-point"> set to position: absolute inside a .nodes-scene container that fills 100 % × 100 % of its parent. Initial coordinates are declared as percentages via the classes .node-a through .node-d (e.g. top: 20%; left: 15%) — no hard-coded pixel values. Each node carries a 135° linear gradient (two tones of the same hue) to simulate a subtle bevel; user-select: none prevents text selection during dragging.

A <svg class="node-lines"> covers the whole scene at position: absolute; inset: 0 with pointer-events: none to never block clicks on the nodes below. The four <line> elements (a→b, b→c, c→d, d→a) define the connections: drawn in light indigo (stroke: rgb(129,140,248)), width 2, stroke-dasharray: 6 4 (6 px dash, 4 px gap), opacity 0.6.

On hover, each node emits a glow halo via box-shadow with a 0.2s transition — the only animation in the provided code. The cursor: grab property (and grabbing on :active) signals drag intent without including any drag logic in the base code.

The x1/y1/x2/y2 attributes of each <line> start at 0,0 and remain invisible until initialized via getBoundingClientRect() on each node pair after DOM render. Real drag behavior — updating SVG coordinates on every move — requires about twenty lines of vanilla JavaScript, shown in the interactive examples below.

Accessibility

  • No prefers-reduced-motion handling in the provided code — the only animation is transition: box-shadow 0.2s on hover, non-repetitive and imperceptible. Pair with @media (prefers-reduced-motion: reduce) { .node-point { transition: none } } if the drag implementation adds further transitions.
  • Nodes are <div> elements with no tabindex or role — not keyboard-reachable in the base state. For an accessible graph, add tabindex="0", role="button", and handle arrow keys to move the active node.
  • The <svg> lines element is purely decorative but lacks aria-hidden="true" — add it to prevent screen readers from traversing it unnecessarily.
  • Contrast fails in the default configuration: white text on amber (#f59e0b) and pink (#ec4899) backgrounds does not reach 4.5:1 WCAG AA at 0.75 rem — use dark text (color:#1e1b4b) or deeper background tones.

Browser compatibility

Pure CSS + native SVG — zero external dependencies, no canvas element required.

Chrome 88+✓ Full
Firefox 87+✓ Full
Safari 15+✓ Full
Edge 88+✓ Full
Mobile iOS✓ Touch OK
Android Chrome✓ Full

If SVG is not supported (very old browsers), connection lines do not appear — colored nodes remain visible and the page stays functional.

The code

Copy the three blocks into your page. No dependencies.

HTML
<div class="anchor-demo">
  <div class="nodes-scene" id="nodesScene">
    <svg class="node-lines">
      <line id="line-ab" x1="0" y1="0" x2="0" y2="0">
      </line>
      <line id="line-bc" x1="0" y1="0" x2="0" y2="0">
      </line>
      <line id="line-cd" x1="0" y1="0" x2="0" y2="0">
      </line>
      <line id="line-da" x1="0" y1="0" x2="0" y2="0">
      </line>
    </svg>
    <div class="node-point node-a" data-node="a">A</div>
    <div class="node-point node-b" data-node="b">B</div>
    <div class="node-point node-c" data-node="c">C</div>
    <div class="node-point node-d" data-node="d">D</div>
  </div>
</div>
CSS
.anchor-demo  {
   position: relative;
   width: 100%;
   height: 220px;
   display: flex;
   align-items: center;
   justify-content: center;
   overflow: hidden;
   }

.anchor-demo *  {
   box-sizing: border-box;
   }

.nodes-scene  {
   position: relative;
   width: 100%;
   height: 100%;
   }

.nodes-scene svg.node-lines  {
   position: absolute;
   inset: 0px;
   width: 100%;
   height: 100%;
   pointer-events: none;
   }

.nodes-scene svg.node-lines line  {
   stroke: rgb(129, 140, 248);
   stroke-width: 2;
   stroke-dasharray: 6, 4;
   opacity: 0.6;
   }

.node-point  {
   position: absolute;
   width: 48px;
   height: 48px;
   border-radius: 50%;
   display: flex;
   align-items: center;
   justify-content: center;
   font-size: 0.75rem;
   font-weight: 700;
   color: rgb(255, 255, 255);
   cursor: grab;
   user-select: none;
   z-index: 2;
   transition: box-shadow 0.2s;
   }

.node-point:active  {
   cursor: grabbing;
   }

.node-point:hover  {
   box-shadow: rgba(129, 140, 248, 0.6) 0px 0px 20px;
   }

.node-a  {
   background: linear-gradient(135deg, rgb(99, 102, 241), rgb(129, 140, 248));
   top: 20%;
   left: 15%;
   }

.node-b  {
   background: linear-gradient(135deg, rgb(236, 72, 153), rgb(244, 114, 182));
   top: 60%;
   left: 55%;
   }

.node-c  {
   background: linear-gradient(135deg, rgb(16, 185, 129), rgb(52, 211, 153));
   top: 25%;
   left: 70%;
   }

.node-d  {
   background: linear-gradient(135deg, rgb(245, 158, 11), rgb(251, 191, 36));
   top: 70%;
   left: 20%;
   }
JavaScript (fx-0476)
// Effet CSS pur — pas de JavaScript nécessaire

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
.anchor-demo height 220px Container height. Set to 100% or 360px to fill a full card or hero section.
.node-point width / height 48px Node diameter. 64 px for longer labels, 32 px for a dense graph with many nodes.
stroke (svg line) rgb(129,140,248) SVG line color. Replace with your accent color or vary per connection type (required vs optional).
stroke-width (svg line) 2 Line thickness. 1 = subtle, 3–4 = strong connections. Can encode edge weight in a weighted graph.
stroke-dasharray (svg line) 6 4 Dash pattern. '0' = solid line (direct link), '2 6' = fine dotted (weak link), '8 3 2 3' = dash-dot.
opacity (svg line) 0.6 Line opacity. 1 = full visibility, 0.3 = receding connections that put nodes in the foreground.
Node backgrounds (.node-a through .node-d background) 4 gradients (indigo, pink, green, amber) Swap for your brand colors or encode node state: green = healthy, red = error, grey = offline.

FAQ

Why are SVG lines invisible on page load?

The x1/y1/x2/y2 attributes of each <line> start at 0 — they must be initialized with getBoundingClientRect() after DOM render. Call the update in a requestAnimationFrame or right after DOMContentLoaded to ensure CSS percentage positions have been computed.

How do I add a fifth node and new connections?

Add a <div class="node-point"> with data-node="e" and its CSS coordinates, then a <line id="line-ae"> in the SVG. The endpoint-update logic is identical — just pass the new node pair to your recalculate function.

Can I add directional arrows to connections?

Yes: define a <marker> inside an SVG <defs> block, then apply marker-end="url(#arrow)" to the target <line> elements. Existing CSS styles (color, width, dashes) stay untouched — only the SVG markup changes.