🏠 back to Observable

SVG constructed from D3 + HTML template not displaying correctly


#1

Example here https://beta.observablehq.com/d/97c7a125f9159357

I would expect the following to display a red circle but it does not. When I inspect the cell output in the element inspector, it shows the correct SVG.

{
  const svg = d3.select(DOM.svg(100, 100))
  const svgNode = svg.node()
  svgNode.append(html`<circle cx=50 cy=50 r=50 fill="red"/>`)
  return svgNode
}

#3

Try

{
  const svg = d3.select(DOM.svg(100, 100))
  svg.html(`<circle cx=50 cy=50 r=50 fill="red"/>`)
  return svg.node()
}

#4

The problem is that the html tagged template literal doesn’t know you are trying to create an svg:circle, and so creates an xhtml:circle element (an HTMLUnknownElement), the same way it would if you tried to create a circle element outside of an SVG in literal HTML:

<body>
  <circle cx=50 cy=50 r=50 fill=red></circle>
</body>

You want the equivalent of this:

<body>
  <svg width=100 height=100>
    <circle cx=50 cy=50 r=50 fill=red></circle>
  </svg>
</body>

So, use the svg tagged template literal instead:

{
  const svgSelection = d3.select(DOM.svg(100, 100))
  const svgNode = svgSelection.node()
  svgNode.append(svg`<circle cx=50 cy=50 r=50 fill=red>`)
  return svgNode
}

#5

Ahh! Thank you Mike, that worked, I was unaware of the difference, I see that now it creates an SVGCircleElement instead of a HTMLUnknownElement, thank you for rapid help!