A B C D

Construction

The nodes are a group / transform g, containing a single a linking to itself href='nodeID', then further containing the visual elements.

    <g transform="translate(x,y)">
      <ellipse rx="R" />
      <text>...</text>
    </g>
  
  1. contains node in single transform matrix
  2. makes it click-to-select via the anchor
  3. :target as getter, and feedback styling
  4. window[location.hash.substring(1)] as getter

Edges are easier when undirected, putting them before the nodes in DOM order renders them underneath; then any path, line, polyline going from source to target position works. For directed edges that should be styled as arrows, the edge end-position has to be offset by r*cos(a) / r*sin(a).

Assigning IDs

One option is to use hyphen-less id for nodes and id='fromid-toid' for edges. Order implicit for directed edges. Then CSS selectors can be used as simply query syntax for JS operations and styling.