Skip to content

SVG loading methods

These are possible loading methods and their tradeoffs

Put whole SVG source code into the DOM every time image is displayed. This is the most popular method.

This is implemented by importing images with ?source query parameter (or source default import option) and inserting the result directly into the DOM:

import imgSrc from "./image.svg?source";
document.getElementById("image-container")!.innerHtml = imgSrc;
  1. Advantages:

    1. Simplicity.
    2. Great customization. This is actually the only option, if you need to manipulate the content, or need more than just CSS styles.
  2. Disadvantages:

    1. Very bad performance. Browser needs to parse and update good number of DOM nodes. It doesn’t really matter when images count is low, but it may slow down the page when 1000+ images are used. Another loading method is always preferred when customization is not required.

Set src attribute of an <img> element:

<img src="/image.svg" />

Or load via background-image CSS property:

.element {
background-image: url("/image.svg");
}

This is implemented via ?url import and url default import option:

import imgUrl from "./image.svg?url";
const img = document.createElement("img");
img.href = imgUrl;
document.body.appendChild(img);
  1. Advantages:

    1. Simplicity.
    2. Great performance thanks to instancing.
  2. Disadvantages:

    1. Lack of any customization, good only for static images. You can’t modify external assets using JS or CSS. The only thing you can do is CSS filters (see warning above!).

Put all images into a single <svg> node (sprite sheet) and wrap each image with a <symbol> element. This improves performance by reducing DOM tree size and enabling instancing.

<!-- Create sprite sheet -->
<svg>
<symbol id="#image1">...</symbol>
<symbol id="#image2">...</symbol>
</svg>
<!-- Use images from the sprite sheet -->
<svg>
<use href="#image1" />
</svg>
<svg>
<use href="#image2" />
</svg>
<svg>
<!-- Content of the linked images won't be duplicated with multiple <use> elements -->
<use href="#image2" />
</svg>

This is implemented by importing images with ?source query parameter (or source default import option) and passing the result to the <SvgImage> or <Svg Icon> component provided by the integrations. See examples for your framework.

  1. Advantages:

    1. Performance is way better than when using whole SVG each time thanks to smaller DOM tree size and instancing.
    2. Images can be customized via CSS, for example, you can set custom stroke and fill colors.
  2. Disadvantages:

    1. Requires a bit of maintenance in form of using provided integrations.
    2. Performance is worse than when linking an image.
    3. Customization is not that great when using whole SVG source code.

Either use source code or base64 in a data URI. Then set src attribute of an <img> element:

<img src="data:..." />

Or load via background-image CSS property:

.element {
background-image: url("data:...");
}

Implemented via ?source-data-uri and base64-data-uri imports, source-data-uri and base64-data-uri default import options.

import srcDataUri from "./image.svg?source-data-uri";
import base64DataUri from "./image.svg?base64-data-uri";
const uris = [srcDataUri, base64DataUri];
for (const uri of uris) {
const img = document.createElement("img");
img.src = imgUrl;
document.body.appendChild(img);
}
  1. Advantages:

    1. Great performance, although a tiny bit worse than when linking an image.
  2. Disadvantages:

    1. Lack of any customization, good only for static images.
    2. Increased memory and traffic usage when linking images.
  1. If you don’t need customization, i.e. you want to display static images, use linking method.
  2. If you only need CSS customization, use symbols. This is preferred option for icons and line art that’s needed to be customized.
  3. If you need heavy customization and interactivity, put whole SVG source code into the DOM.
  4. As for the data URI, not sure why you would need it. It’s implemented just for completeness sake.