Post

Importing SVG Into Sites via HTML / JavaScript

Old Version of Importing SVG

Previously I was under the impression that the only functional way to have a .svg file accessible as a spritesheet was via something similar to the code below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/** 
 * Fetch `.svg` file from URL as an `<svg>` spritesheet element
 * - Automatically appends `<svg>` to body, and hides it
 * 
 * @param {string} url The URL for the `.svg` file
 * @returns {Promise<SVGElement>} Promise of the `<svg>` element
 * @throws For an unsuccessful fetch
 */
async function fetchSpritesheet(url) {
    const svg = await fetchSVGElement(url, true);
    svg.style.display = 'none';
    document.body.append(svg);
    return svg;
}

/** 
 * Create an `<svg>` sprite from a given symbol id
 * - Requires a pre-loaded `<svg>` spritesheet in the DOM (eg. via `fetchSpritesheet`)
 * 
 * @param {string} id The symbol id from the pre-loaded spritesheet
 * @returns {SVGElement} The `<svg>` sprite element
 */
function createSprite(id) {
    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
    use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', `#${id}`);
    svg.appendChild(use);
    return svg;
}

await fetchSpritesheet('https://example.com/file.svg');
const container = document.getElementById('container');
const sprite = createSprite('test');
sprite.classList.add('sprite');
container.appendChild(sprite);

In the example, the .svg file is loaded as hidden <svg> element into the DOM, and references are made via the <use> tag in the format below

1
2
3
<svg>
  <use href="#save"></use>
</svg>

The href="#save" references an icon from the loaded .svg file. An abridged version can be seen below where save matches a <symbol> id

1
2
3
4
5
6
7
8
9
10
11
<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <symbol id="save" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
      stroke-linejoin="round">
      <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z">
      </path>
      <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"></path>
      <path d="M7 3v4a1 1 0 0 0 1 1h7"></path>
    </symbol>
  </defs>
</svg>

New Version of Importing SVG

It turns out you can make direct reference to a .svg file and id, without adding it to the DOM. I was aware of this feature but seemed to have issues in certain use cases at the time, which I cannot remember, and so stopped using the method

1
2
3
4
5
<button id="save-button" title="Save">
  <svg>
    <use href="/assets/svg/lucide.svg#save"></use>
  </svg>
</button>
This post is licensed under CC BY 4.0 by the author.