Load and Inject SVG Dynamically Using Fetch API
This article explains how to asynchronously retrieve external SVG
files using JavaScript’s Fetch API and insert them directly into the
Document Object Model (DOM) as inline elements. Loading SVGs inline
rather than embedding them inside <img> or
<object> tags gives you complete control over the
graphic, allowing you to manipulate paths with JavaScript and
dynamically restyle elements using CSS properties like fill
and stroke.
Why Inject Inline SVGs?
Embedding an SVG as a standard image tag
(<img src="icon.svg">) prevents access to the SVG’s
internal elements via the DOM. Fetching the raw SVG markup and injecting
it inline provides several benefits:
- Full CSS control, including animations, hover states, and dynamic
theming using
currentColor. - Direct DOM access to individual paths, groups, and nodes for event listeners.
- Reduced initial HTML payload by loading complex vector graphics on demand.
Step-by-Step Implementation Using DOMParser
Using the browser’s native DOMParser is the cleanest and
most robust method. It parses the SVG text into an XML Document,
allowing you to validate the element before mounting it into the
page.
1. The JavaScript Function
async function injectSVG(url, targetSelector) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch SVG: ${response.status} ${response.statusText}`);
}
const svgText = await response.text();
// Parse the text into an XML DOM document
const parser = new DOMParser();
const svgDoc = parser.parseFromString(svgText, 'image/svg+xml');
const svgElement = svgDoc.querySelector('svg');
// Check if the parser returned a valid SVG element
if (!svgElement || svgDoc.querySelector('parsererror')) {
throw new Error('Invalid SVG markup received');
}
// Locate the container and append the SVG
const container = document.querySelector(targetSelector);
if (container) {
container.replaceChildren(svgElement);
} else {
console.warn(`Target container "${targetSelector}" not found.`);
}
} catch (error) {
console.error('SVG injection error:', error);
}
}2. The HTML Structure
Prepare a placeholder element where the SVG should be mounted:
<div id="icon-container" class="icon-wrapper"></div>3. Executing the Function
Call the function by providing the URL path to your SVG file and the CSS selector of the container element:
injectSVG('/assets/icons/logo.svg', '#icon-container');Alternative: Direct
innerHTML Injection
For simple use cases, you can assign the fetched text directly to an
element’s innerHTML:
async function loadSimpleSVG(url, containerId) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const svgText = await response.text();
document.getElementById(containerId).innerHTML = svgText;
} catch (error) {
console.error('Error loading SVG:', error);
}
}Important Considerations
- Cross-Origin Resource Sharing (CORS): The Fetch API
is subject to standard CORS policies. Ensure external SVG files are
hosted on the same origin or served with appropriate
Access-Control-Allow-Originheaders. - Security (XSS Risks): SVGs can contain embedded
<script>tags. If you are loading SVGs from untrusted user inputs or third-party sources, sanitize the markup using a library like DOMPurify before injecting it into your page. - Performance: When loading the same icon multiple
times, cache the fetched SVG string in a JavaScript object or
Mapto avoid redundant network requests.