How to embed an SVG with JavaScript

- 6 min read

Embedding an SVG with JavaScript is a bit different than creating normal HTML elements.

Before proceeding with this tutorial, here’s a basic reproduction of an SVG in JavaScript (for those that are tl;dr prone):

function createPythonLogoSVG() {
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  const topSnake = document.createElementNS("http://www.w3.org/2000/svg", "path");
  const bottomSnake = document.createElementNS("http://www.w3.org/2000/svg", "path");
  svg.setAttribute("viewBox", "0 0 512 512");
  topSnake.setAttribute("d", "M193.46 249.056a65.316 65.316 0 0 1 11.586-1.041l-3.122-.015h103.823c4.503 0 8.806-.617 12.908-1.754 19.37-5.363 33.345-22.537 33.345-43.663v-87.224c0-24.832-21.15-43.484-46.289-47.606-15.931-2.624-39.258-3.827-55.089-3.749-15.829.086-30.981 1.404-44.277 3.749C167.143 74.576 160 88.928 160 115.359V144h96v16H128.82c-35.628 0-64.538 42.571-64.813 95.242-.002.253-.007.505-.007.758 0 9.523.94 18.72 2.685 27.404C74.648 323.07 99.451 352 128.82 352H144v-45.935c0-26.827 20.146-51.733 49.46-57.009zm10.196-122.054c-9.592 0-17.384-7.785-17.384-17.403 0-9.664 7.774-17.52 17.384-17.52 9.574 0 17.399 7.855 17.399 17.52.001 9.618-7.809 17.403-17.399 17.403z");
  bottomSnake.setAttribute("d", "M443.951 222.543C434.78 186.021 411.033 160 383.18 160H368v40.672c0 33.915-22.286 58.474-49.489 62.681a53.943 53.943 0 0 1-8.301.646H206.351a51.41 51.41 0 0 0-13.049 1.672C174.18 270.689 160 286.6 160 307.236v87.227c0 24.832 24.977 39.426 49.481 46.551 29.327 8.531 61.267 10.068 96.366 0C329.15 434.354 352 420.893 352 394.463V368h-96v-16h127.18c25.24 0 47.107-21.365 57.814-52.549C445.474 286.404 448 271.641 448 256c0-11.768-1.433-23.038-4.049-33.457zM307.867 382.82c9.59 0 17.381 7.785 17.381 17.4 0 9.65-7.791 17.521-17.381 17.521-9.577 0-17.399-7.871-17.399-17.521 0-9.63 7.806-17.4 17.399-17.4z");
  svg.appendChild(topSnake);
  svg.appendChild(bottomSnake);
  return svg;
}

document.body.appendChild(createPythonLogoSVG());

The Python logo is a trademark of the Python Software Foundation. The SVG used as the source for this code is from the Ionicons icon font, version 4.5.1.

Start with an SVG

As mentioned above, we’re using the Ionicons font’s implementation of the Python logo. The SVG source code from their site is (whitespaced added for readability):

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
  <path d="M193.46 249.056a65.316 65.316 0 0 1 11.586-1.041l-3.122-.015h103.823c4.503 0 8.806-.617 12.908-1.754 19.37-5.363 33.345-22.537 33.345-43.663v-87.224c0-24.832-21.15-43.484-46.289-47.606-15.931-2.624-39.258-3.827-55.089-3.749-15.829.086-30.981 1.404-44.277 3.749C167.143 74.576 160 88.928 160 115.359V144h96v16H128.82c-35.628 0-64.538 42.571-64.813 95.242-.002.253-.007.505-.007.758 0 9.523.94 18.72 2.685 27.404C74.648 323.07 99.451 352 128.82 352H144v-45.935c0-26.827 20.146-51.733 49.46-57.009zm10.196-122.054c-9.592 0-17.384-7.785-17.384-17.403 0-9.664 7.774-17.52 17.384-17.52 9.574 0 17.399 7.855 17.399 17.52.001 9.618-7.809 17.403-17.399 17.403z"/>
  <path d="M443.951 222.543C434.78 186.021 411.033 160 383.18 160H368v40.672c0 33.915-22.286 58.474-49.489 62.681a53.943 53.943 0 0 1-8.301.646H206.351a51.41 51.41 0 0 0-13.049 1.672C174.18 270.689 160 286.6 160 307.236v87.227c0 24.832 24.977 39.426 49.481 46.551 29.327 8.531 61.267 10.068 96.366 0C329.15 434.354 352 420.893 352 394.463V368h-96v-16h127.18c25.24 0 47.107-21.365 57.814-52.549C445.474 286.404 448 271.641 448 256c0-11.768-1.433-23.038-4.049-33.457zM307.867 382.82c9.59 0 17.381 7.785 17.381 17.4 0 9.65-7.791 17.521-17.381 17.521-9.577 0-17.399-7.871-17.399-17.521 0-9.63 7.806-17.4 17.399-17.4z"/>
</svg>

Create the SVG in Javascript

Since SVGs are XML documents, we shouldn’t use document.createElement() but should instead use document.createElementNS() that let’s us secify the namespace URI to associate with the element.

The particular SVG we’re working with contains three elements: the <svg> parent and two child <path> elements. To reproduce the SVG we need to be sure that we reproduce this structure exactly.

Create the SVG element

With the exception of the using document.createElementNS() this code looks like any reproduction of an HTML element in JavaScript:

// Create the element, supporting its xmlns attribute.
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
// Reproduce the viewBox attribute.
svg.setAttribute("viewBox", "0 0 512 512");

Create the paths

The paths follow the same concept as the SVG, because they are part of the SVG’s XML document, they should also be created with the document.createElementNS() method:

const topSnake = document.createElementNS("http://www.w3.org/2000/svg", "path");
const bottomSnake = document.createElementNS("http://www.w3.org/2000/svg", "path");

topSnake.setAttribute("d", "M193.46 249.056a65.316 65.316 0 0 1 11.586-1.041l-3.122-.015h103.823c4.503 0 8.806-.617 12.908-1.754 19.37-5.363 33.345-22.537 33.345-43.663v-87.224c0-24.832-21.15-43.484-46.289-47.606-15.931-2.624-39.258-3.827-55.089-3.749-15.829.086-30.981 1.404-44.277 3.749C167.143 74.576 160 88.928 160 115.359V144h96v16H128.82c-35.628 0-64.538 42.571-64.813 95.242-.002.253-.007.505-.007.758 0 9.523.94 18.72 2.685 27.404C74.648 323.07 99.451 352 128.82 352H144v-45.935c0-26.827 20.146-51.733 49.46-57.009zm10.196-122.054c-9.592 0-17.384-7.785-17.384-17.403 0-9.664 7.774-17.52 17.384-17.52 9.574 0 17.399 7.855 17.399 17.52.001 9.618-7.809 17.403-17.399 17.403z");

bottomSnake.setAttribute("d", "M443.951 222.543C434.78 186.021 411.033 160 383.18 160H368v40.672c0 33.915-22.286 58.474-49.489 62.681a53.943 53.943 0 0 1-8.301.646H206.351a51.41 51.41 0 0 0-13.049 1.672C174.18 270.689 160 286.6 160 307.236v87.227c0 24.832 24.977 39.426 49.481 46.551 29.327 8.531 61.267 10.068 96.366 0C329.15 434.354 352 420.893 352 394.463V368h-96v-16h127.18c25.24 0 47.107-21.365 57.814-52.549C445.474 286.404 448 271.641 448 256c0-11.768-1.433-23.038-4.049-33.457zM307.867 382.82c9.59 0 17.381 7.785 17.381 17.4 0 9.65-7.791 17.521-17.381 17.521-9.577 0-17.399-7.871-17.399-17.521 0-9.63 7.806-17.4 17.399-17.4z");

Note, your SVG may contain <g> or other SVG elements. They should be reproduced following the same practice by using document.createElementNS() and setting all of their attributes using el.setAttribute("attribute name", "attribute value"), like we set the d attributes above.

Putting the elements together

Now that we have our svg, topSnake, and bottomSnake elements, we need to make the snake path elements children of the SVG (to reproduce the structure of the SVG’s XML).

// Since topSnake is appended first, it will be the first child.
svg.appendChild(topSnake);
// Bottom snake is appended second, so it becomes the second---and in this example, last child.
svg.appendChild(bottomSnake);

The svg element can now be added anywhere in your DOM desired using normal JavaScript methods. For example to append as the last element of the <body>:

document.body.appendChild(svg);

A more complex example

To demonstrate an SVG with an additional layer of complexity, we’ll introduce a <g> tag to group the top and bottom snake elements and rotate the logo 90°.

function createRotatedPythonLogoSVG() {
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  // Create the group element.
  const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
  const topSnake = document.createElementNS("http://www.w3.org/2000/svg", "path");
  const bottomSnake = document.createElementNS("http://www.w3.org/2000/svg", "path");
  svg.setAttribute("viewBox", "0 0 512 512");
  // Add the transform property to the group with rotation:
  // 90 is the rotation
  // 256 and 256 is the center point of the SVG, based on the viewBox that will be the parent of the group.
  group.setAttribute("transform", "rotate(90 256 256)");
  topSnake.setAttribute("d", "M193.46 249.056a65.316 65.316 0 0 1 11.586-1.041l-3.122-.015h103.823c4.503 0 8.806-.617 12.908-1.754 19.37-5.363 33.345-22.537 33.345-43.663v-87.224c0-24.832-21.15-43.484-46.289-47.606-15.931-2.624-39.258-3.827-55.089-3.749-15.829.086-30.981 1.404-44.277 3.749C167.143 74.576 160 88.928 160 115.359V144h96v16H128.82c-35.628 0-64.538 42.571-64.813 95.242-.002.253-.007.505-.007.758 0 9.523.94 18.72 2.685 27.404C74.648 323.07 99.451 352 128.82 352H144v-45.935c0-26.827 20.146-51.733 49.46-57.009zm10.196-122.054c-9.592 0-17.384-7.785-17.384-17.403 0-9.664 7.774-17.52 17.384-17.52 9.574 0 17.399 7.855 17.399 17.52.001 9.618-7.809 17.403-17.399 17.403z");
  bottomSnake.setAttribute("d", "M443.951 222.543C434.78 186.021 411.033 160 383.18 160H368v40.672c0 33.915-22.286 58.474-49.489 62.681a53.943 53.943 0 0 1-8.301.646H206.351a51.41 51.41 0 0 0-13.049 1.672C174.18 270.689 160 286.6 160 307.236v87.227c0 24.832 24.977 39.426 49.481 46.551 29.327 8.531 61.267 10.068 96.366 0C329.15 434.354 352 420.893 352 394.463V368h-96v-16h127.18c25.24 0 47.107-21.365 57.814-52.549C445.474 286.404 448 271.641 448 256c0-11.768-1.433-23.038-4.049-33.457zM307.867 382.82c9.59 0 17.381 7.785 17.381 17.4 0 9.65-7.791 17.521-17.381 17.521-9.577 0-17.399-7.871-17.399-17.521 0-9.63 7.806-17.4 17.399-17.4z");
  // Instead of appending the snakes to the SVG, we append them to the group:
  group.appendChild(topSnake);
  group.appendChild(bottomSnake);
  // We then append the group to the SVG:
  svg.appendChild(group);
  return svg;
}

document.body.appendChild(createRotatedPythonLogoSVG());

Super complex SVGs

If you have an incredibly complex SVG, such as the Python Powered logo you probably won’t want to embed your logo within JavaScript as the resulting code will be very time consuming to implement and will be quite complex.

Often complicated SVGs like this are created with a tool that embeds a lot of unnecessary structure and styling. This overhead can often be dramatically reduced by a skilled designer putting in (a lot of) additional effort to pare down the SVG’s complexity.

Author

Cody Craven enjoys sharing tidbits of information that he learns through his life-long journey developing websites and configuring web servers.

When at work, Cody can often be found banging his head against his keyboard for hours days weeks-on-end trying to solve technical issues that would otherwise prevent his teammates from creating Member value at AAA.

All content that Cody contributes to this site are his own ideas and do not necessarily represent AAA's positions or opinions.